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