打印

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

[复制链接]
673|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vsf|  楼主 | 2018-4-16 14:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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状态,等到高层处理完事件后,重新初始化接收状态机启动接收。

使用特权

评论回复

相关帖子

发新帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

vsf

27

主题

60

帖子

6

粉丝