VSF应用实例--解析蓝牙串口HCI(3)代码

[复制链接]
925|0
 楼主| vsf 发表于 2018-4-16 14:23 | 显示全部楼层 |阅读模式
本帖最后由 vsf 于 2018-4-17 13:55 编辑
  1. static struct vsfsm_state_t *hci_transport_h4_evt_handler(struct vsfsm_t *sm,
  2.                 vsfsm_evt_t evt)
  3. {
  4.         struct hci_transport_h4_param_t *h4param =
  5.                         (struct hci_transport_h4_param_t *)sm->user_data;
  6.         struct vsf_bufstream_t *bufstream;
  7.         uint8_t *ptr;

  8.         switch (evt)
  9.         {
  10.         case VSFSM_EVT_INIT:
  11.                 {
  12.                         struct usart_stream_t *usart_stream = h4param->usart_stream;
  13.                         struct vsf_stream_t *stream;

  14.                         h4param->rx.stream.mem.read = false;
  15.                         stream = usart_stream->stream_rx = &h4param->rx.stream.stream;
  16.                         stream->op = &bufstream_op;
  17.                         stream->callback_rx.param = h4param;
  18.                         stream->callback_rx.on_inout = hci_transport_h4_on_in;

  19.                         usart_stream_init(usart_stream);
  20.                         stream_connect_rx(usart_stream->stream_rx);
  21.                 }
  22.                 break;
  23.         case HCI_EVT_IN:
  24.                 if (h4param->rx.state == HCI_RX_RECEIVED)
  25.                 {
  26.                         bufstream = &h4param->rx.stream;
  27.                         ptr = &h4param->rx.buffer[HCI_INCOMING_PRE_SIZE];
  28.                         h4param->packet_handler(ptr[0], &ptr[1],
  29.                                 (bufstream->mem.buffer.buffer - ptr) + bufstream->mem.buffer.size - 1);

  30.                         h4param->rx.state = HCI_RX_IDLE;
  31.                         hci_transport_h4_on_in(h4param);
  32.                 }
  33.                 break;
  34.         }
  35.         return NULL;
  36. }
这里是任务的事件驱动代码,INIT事件中,初始化了接收流,类型是bufstream。对于bufstream,可以自己看VSF中,component/fundation/stream里的代码。
然后初始化串口流,对于接收串口数据来说,串口流模块是发送端,因为串口流模块在接收到串口数据的时候,会写入到流,发送端可以写数据到流。
串口流初始化后,实际上接收流的发送端就连接上了,后面就是连接接收端,这样流就可以运行了。

这里一个关键的函数是:hci_transport_h4_on_in,在接收流收到数据的时候被调用,注意,这个函数是可能在中断中被调用的。
  1. static void hci_transport_h4_on_in(void *param)
  2. {
  3.         struct hci_transport_h4_param_t *h4param =
  4.                         (struct hci_transport_h4_param_t *)param;
  5.         struct vsf_bufstream_t *bufstream = &h4param->rx.stream;
  6.         uint8_t *ptr = &h4param->rx.buffer[0];
  7.         struct vsf_buffer_t buffer;

  8.         if (h4param->opened)
  9.         {
  10.                 if (STREAM_GET_FREE_SIZE(bufstream))
  11.                         return;

  12.                 switch (h4param->rx.state)
  13.                 {
  14.                 case HCI_RX_IDLE:
  15.                 hci_transport_h4_idle:
  16.                         h4param->rx.state++;
  17.                         buffer.buffer = ptr;
  18.                         buffer.size = 1;
  19.                         break;
  20.                 case HCI_RX_TYPE:
  21.                         h4param->rx.state++;
  22.                         buffer.buffer = &ptr[1];
  23.                         switch (ptr[0])
  24.                         {
  25.                         case HCI_ACL_DATA_PACKET:
  26.                                 buffer.size = HCI_ACL_HEADER_SIZE;
  27.                                 break;
  28.                         case HCI_SCO_DATA_PACKET:
  29.                                 buffer.size = HCI_SCO_HEADER_SIZE;
  30.                                 break;
  31.                         case HCI_EVENT_PACKET:
  32.                                 buffer.size = HCI_EVENT_HEADER_SIZE;
  33.                                 break;
  34.                         default:
  35.                         hci_transport_h4_reset:
  36.                                 h4param->rx.state = HCI_RX_IDLE;
  37.                                 goto hci_transport_h4_idle;
  38.                         }
  39.                         break;
  40.                 case HCI_RX_HEADER:
  41.                         switch (ptr[0])
  42.                         {
  43.                         case HCI_ACL_DATA_PACKET:
  44.                                 buffer.size = GET_LE_U16(&ptr[3]);
  45.                                 buffer.buffer = &ptr[1 + HCI_ACL_HEADER_SIZE];
  46.                                 if (HCI_ACL_HEADER_SIZE + buffer.size > HCI_PACKET_BUFFER_SIZE)
  47.                                         goto hci_transport_h4_reset;
  48.                                 break;
  49.                         case HCI_SCO_DATA_PACKET:
  50.                                 buffer.size = ptr[3];
  51.                                 buffer.buffer = &ptr[1 + HCI_SCO_HEADER_SIZE];
  52.                                 break;
  53.                         case HCI_EVENT_PACKET:
  54.                                 buffer.size = ptr[2];
  55.                                 buffer.buffer = &ptr[1 + HCI_EVENT_HEADER_SIZE];
  56.                                 break;
  57.                         }

  58.                         h4param->rx.state++;
  59.                         if (buffer.size)
  60.                                 break;
  61.                 case HCI_RX_DATA:
  62.                         h4param->rx.state++;
  63.                         vsfsm_post_evt_pending(&h4param->sm, HCI_EVT_IN);
  64.                 case HCI_RX_RECEIVED:
  65.                         return;
  66.                 }
  67.                 STREAM_READ(bufstream, &buffer);
  68.         }
  69. }
在启动的时候,会调用一次hci_transport_h4_on_in,这时候,rx.state是IDLE,会设置buffer接收1个字节报文类型(通过调用STREAM_READ)。
然后,这里就是一个状态机了,在RX_DATA接受完数据后,就发送HCI_EVT_IN事件,并且进入RECEIVED状态,等到高层处理完事件后,重新初始化接收状态机启动接收。
vsf

27

主题

60

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部