本次分析是基于Windows平台,HCI-H4传输方式
从源码层面分析HCI层是如何从uart读取数据、HCI层的数据怎样传给uart最后发给蓝牙Controller的。
应用层配置串口驱动 port\windows-h4\main.c
// init HCI
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);
串口驱动 platform\windows\btstack_uart_block_windows.c
// block read
static uint16_t read_bytes_len;//指定读取字节数,hci层传递过来的
static uint8_t * read_bytes_data;//数据存放缓冲区,hci层传递过来的
// callbacks
static void (*block_sent)(void);//发送回调函数
static void (*block_received)(void);//接收回调函数指针,如果是H4接口,则指向 hci_transport_h4_block_read 函数
static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){//读取串口数据,在hci_transport_h4.c中调用 btstack_uart->receive_block
// setup async read
read_bytes_data = buffer;//设置存放数据的缓冲区
read_bytes_len = len;//设置读取的字节数
// go 启动读取
btstack_uart_windows_receive_engine();
}
static void btstack_uart_windows_set_block_received( void (*block_handler)(void)){//在hci_transport_h4.c中调用 btstack_uart->set_block_received
block_received = block_handler;
}
static const btstack_uart_block_t btstack_uart_windows = {
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_windows_init,
/* int (*open)(void); */ &btstack_uart_windows_open,
/* int (*close)(void); */ &btstack_uart_windows_close_new,
/* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_windows_set_block_received,//设置接收回调函数
/* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_windows_set_block_sent,
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_windows_set_baudrate,
/* int (*set_parity)(int parity); */ &btstack_uart_windows_set_parity,
/* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_windows_set_flowcontrol,
/* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_windows_receive_block,//接收函数
/* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_windows_send_block,
/* int (*get_supported_sleep_modes); */ NULL,
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
NULL, NULL, NULL, NULL,
};
const btstack_uart_block_t * btstack_uart_block_windows_instance(void){
return &btstack_uart_windows;
}
大致思路是:在hci层定义数据存放缓冲区、读取字节数、hci状态(hci_state),根据hci状态读取指定字节数据,读完后先简单分类、切换hci状态,然后继续读取,直到读完一个数据包。
hci_transport_h4_open函数中启动读取数据,hci_transport_h4_trigger_next_read调用接收函数
// init rx + tx state machines
hci_transport_h4_reset_statemachine();//复位h4状态、数据存放缓冲区、读取字节数
hci_transport_h4_trigger_next_read();//开始读取串口数据
static void hci_transport_h4_reset_statemachine(void){
h4_state = H4_W4_PACKET_TYPE;
read_pos = 0;
bytes_to_read = 1;
}
static void hci_transport_h4_trigger_next_read(void){
// log_info("hci_transport_h4_trigger_next_read: %u bytes", bytes_to_read);
btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read); //调用接收函数
}
btstack_uart->receive_block 指向 btstack_uart_windows_receive_block 函数
static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){//读取串口数据,在hci_transport_h4.c中调用 btstack_uart->receive_block
// setup async read
read_bytes_data = buffer;//设置存放数据的缓冲区
read_bytes_len = len;//设置读取的字节数
// go 启动读取
btstack_uart_windows_receive_engine();
}
读完一个数据包后句开始处理数据 ,调用包事件处理函数
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);
}