btstack源码分析---HCI层与硬件接口的数据传输

本次分析是基于Windows平台,HCI-H4传输方式
从源码层面分析HCI层是如何从uart读取数据、HCI层的数据怎样传给uart最后发给蓝牙Controller的。

一、从uart读取数据

1、配置、初始化

应用层配置串口驱动 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;
}
2、读取数据

大致思路是:在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);
}

二、hci 层写数据到串口

1、配置、初始化
2、发送数据

你可能感兴趣的:(蓝牙学习,物联网)