btstack源码分析---HCI层数据处理

本次分析是基于Windows平台,HCI-H4传输方式
从源码层面分析HCI层从硬件获取到数据后怎么继续处理,如EVENT、ACL数据是怎么传到本层(HCI层)和上层的,又是如何处理的。

1、packet_handler 的调用

HCI层数据的处理是在 hci.c文件的 packet_handler 函数中进行的,下面开始分析 packet_handler 函数是怎么被调用的
hci 层读取完一个数据包后就调用hci_transport_h4_packet_complete,开始处理数据

//hci_transport_h4_block_read函数
case H4_W4_PAYLOAD:
            hci_transport_h4_packet_complete();

看下 hci_transport_h4_packet_complete 函数实现,发现 hci_transport_h4_packet_handler(hci_packet[0], &hci_packet[1], packet_len);就是数据包处理函数,它是一个函数指针,在定义时赋值了一个虚拟处理器。

static void hci_transport_h4_packet_complete(void){
#ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
    if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE
            && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){
#ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
                if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){
                    // detect TI CC256x controller based on manufacturer
                    log_info("Detected CC256x controller");
                    baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED;
                } else {
                    // work around not needed
                    log_info("Bluetooth controller not by TI");
                    baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
                }
#endif
#ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
                if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){
                    // detect Cypress controller based on manufacturer
                    log_info("Detected Cypress controller");
                    baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED;
                } else {
                    // work around not needed
                    log_info("Bluetooth controller not by Cypress");
                    baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
                }
#endif
            }
#endif
    uint16_t packet_len = read_pos-1u;

    // reset state machine before delivering packet to stack as it might close the transport
    hci_transport_h4_reset_statemachine();
    hci_transport_h4_packet_handler(hci_packet[0], &hci_packet[1], packet_len);//实际调用的是 hci.c 中的 packet_handler 函数
}

static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
    UNUSED(packet_type);
    UNUSED(packet);
    UNUSED(size);
}
static void (*hci_transport_h4_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;

有一个注册函数会为 hci_transport_h4_packet_handler 赋值,这样就会替换掉定义时赋值的虚拟处理器,继续追踪,在哪里注册了事件处理函数,即在哪里调用了 hci_transport_h4_register_packet_handler 函数。

static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
    hci_transport_h4_packet_handler = handler;
}

发现 hci_transport_h4_register_packet_handler 是hci_transport接口实例 hci_transport_h4 的一个属性,接下来就要找哪里调用了 register_packet_handler

// configure and return h4 singleton
static const hci_transport_t hci_transport_h4 = {
        /* const char * name; */                                        "H4",
        /* void   (*init) (const void *transport_config); */            &hci_transport_h4_init,
        /* int    (*open)(void); */                                     &hci_transport_h4_open,
        /* int    (*close)(void); */                                    &hci_transport_h4_close,
        /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_h4_register_packet_handler,//注册包处理函数
        /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_h4_can_send_now,
        /* int    (*send_packet)(...); */                               &hci_transport_h4_send_packet,
        /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_h4_set_baudrate,
        /* void   (*reset_link)(void); */                               NULL,
        /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
};
// @deprecated
const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) {
    btstack_uart = (const btstack_uart_t *) uart_driver;
    return &hci_transport_h4;
}

最后是在hci.c的hci_init初始化函数中调用了 register_packet_handler ,注册了数据包处理函数

/** main.c **/
    const btstack_uart_block_t * uart_driver = btstack_uart_block_windows_instance();
    const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
    hci_init(transport, (void*) &config);

/** hci.c **/
void hci_init(const hci_transport_t *transport, const void *config){
	/**省略前面的代码**/
    // reference to use transport layer implementation
    hci_stack->hci_transport = transport;//
        
    // reference to used config
    hci_stack->config = config;
    
    // setup pointer for outgoing packet buffer
    hci_stack->hci_packet_buffer = &hci_stack->hci_packet_buffer_data[HCI_OUTGOING_PRE_BUFFER_SIZE];

    // max acl payload size defined in config.h
    hci_stack->acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
    
    // register packet handlers with transport
    transport->register_packet_handler(&packet_handler);//注册数据包处理函数
	/**省略后面的代码**/
    }

再看下数据包处理函数 packet_handler 是怎么处理数据的,packet_handler 在hci.c文件中,到这里数据就到了 hci 层的核心处理区,按照协议文档对数据进行处理。继续看看事件的处理 event_handler

static void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
    hci_dump_packet(packet_type, 1, packet, size);
    switch (packet_type) {
        case HCI_EVENT_PACKET:
            event_handler(packet, size);
            break;
        case HCI_ACL_DATA_PACKET:
            acl_handler(packet, size);
            break;
#ifdef ENABLE_CLASSIC
        case HCI_SCO_DATA_PACKET:
            sco_handler(packet, size);
            break;
#endif
#ifdef ENABLE_LE_ISOCHRONOUS_STREAMS
        case HCI_ISO_DATA_PACKET:
            hci_iso_packet_handler(packet, size);
            break;
#endif
        default:
            break;
    }
}

event_handler 函数特别多,差不多1000行,就不贴源码了。
在这里插入图片描述
event_handler 函数最后调用 hci_emit_event(packet, size, 0); 将事件发送到上层协议,上层协议再对数据进行处理;细节分析TODO

    // notify upper stack
	hci_emit_event(packet, size, 0);   // don't dump, already happened in packet handler

你可能感兴趣的:(蓝牙学习,linux)