本帖最后由 vsf 于 2018-4-17 13:55 编辑
static struct vsfsm_state_t *hci_transport_h4_evt_handler(struct vsfsm_t *sm,
vsfsm_evt_t evt)
{
struct hci_transport_h4_param_t *h4param =
(struct hci_transport_h4_param_t *)sm->user_data;
struct vsf_bufstream_t *bufstream;
uint8_t *ptr;
switch (evt)
{
case VSFSM_EVT_INIT:
{
struct usart_stream_t *usart_stream = h4param->usart_stream;
struct vsf_stream_t *stream;
h4param->rx.stream.mem.read = false;
stream = usart_stream->stream_rx = &h4param->rx.stream.stream;
stream->op = &bufstream_op;
stream->callback_rx.param = h4param;
stream->callback_rx.on_inout = hci_transport_h4_on_in;
usart_stream_init(usart_stream);
stream_connect_rx(usart_stream->stream_rx);
}
break;
case HCI_EVT_IN:
if (h4param->rx.state == HCI_RX_RECEIVED)
{
bufstream = &h4param->rx.stream;
ptr = &h4param->rx.buffer[HCI_INCOMING_PRE_SIZE];
h4param->packet_handler(ptr[0], &ptr[1],
(bufstream->mem.buffer.buffer - ptr) + bufstream->mem.buffer.size - 1);
h4param->rx.state = HCI_RX_IDLE;
hci_transport_h4_on_in(h4param);
}
break;
}
return NULL;
}
这里是任务的事件驱动代码,INIT事件中,初始化了接收流,类型是bufstream。对于bufstream,可以自己看VSF中,component/fundation/stream里的代码。
然后初始化串口流,对于接收串口数据来说,串口流模块是发送端,因为串口流模块在接收到串口数据的时候,会写入到流,发送端可以写数据到流。
串口流初始化后,实际上接收流的发送端就连接上了,后面就是连接接收端,这样流就可以运行了。
这里一个关键的函数是:hci_transport_h4_on_in,在接收流收到数据的时候被调用,注意,这个函数是可能在中断中被调用的。
static void hci_transport_h4_on_in(void *param)
{
struct hci_transport_h4_param_t *h4param =
(struct hci_transport_h4_param_t *)param;
struct vsf_bufstream_t *bufstream = &h4param->rx.stream;
uint8_t *ptr = &h4param->rx.buffer[0];
struct vsf_buffer_t buffer;
if (h4param->opened)
{
if (STREAM_GET_FREE_SIZE(bufstream))
return;
switch (h4param->rx.state)
{
case HCI_RX_IDLE:
hci_transport_h4_idle:
h4param->rx.state++;
buffer.buffer = ptr;
buffer.size = 1;
break;
case HCI_RX_TYPE:
h4param->rx.state++;
buffer.buffer = &ptr[1];
switch (ptr[0])
{
case HCI_ACL_DATA_PACKET:
buffer.size = HCI_ACL_HEADER_SIZE;
break;
case HCI_SCO_DATA_PACKET:
buffer.size = HCI_SCO_HEADER_SIZE;
break;
case HCI_EVENT_PACKET:
buffer.size = HCI_EVENT_HEADER_SIZE;
break;
default:
hci_transport_h4_reset:
h4param->rx.state = HCI_RX_IDLE;
goto hci_transport_h4_idle;
}
break;
case HCI_RX_HEADER:
switch (ptr[0])
{
case HCI_ACL_DATA_PACKET:
buffer.size = GET_LE_U16(&ptr[3]);
buffer.buffer = &ptr[1 + HCI_ACL_HEADER_SIZE];
if (HCI_ACL_HEADER_SIZE + buffer.size > HCI_PACKET_BUFFER_SIZE)
goto hci_transport_h4_reset;
break;
case HCI_SCO_DATA_PACKET:
buffer.size = ptr[3];
buffer.buffer = &ptr[1 + HCI_SCO_HEADER_SIZE];
break;
case HCI_EVENT_PACKET:
buffer.size = ptr[2];
buffer.buffer = &ptr[1 + HCI_EVENT_HEADER_SIZE];
break;
}
h4param->rx.state++;
if (buffer.size)
break;
case HCI_RX_DATA:
h4param->rx.state++;
vsfsm_post_evt_pending(&h4param->sm, HCI_EVT_IN);
case HCI_RX_RECEIVED:
return;
}
STREAM_READ(bufstream, &buffer);
}
}
在启动的时候,会调用一次hci_transport_h4_on_in,这时候,rx.state是IDLE,会设置buffer接收1个字节报文类型(通过调用STREAM_READ)。
然后,这里就是一个状态机了,在RX_DATA接受完数据后,就发送HCI_EVT_IN事件,并且进入RECEIVED状态,等到高层处理完事件后,重新初始化接收状态机启动接收。
|