btstack源码分析-btstack_main(我方已到达战场)

历史的帷幕徐徐落下,新的时代即将到来,从此人类踏入了新纪元...

在btstack/example目录下,每个文件都是一个示例程序,每个示例程序都有一个btstack_main函数,每个示例程序可以扮演client、service、可以是包含电池服务的外围设备或心跳服务的外围设备等等。

本文分析以le_data_channel_client.c为例,其btstack_main定义如下:

int btstack_main(int argc, const char * argv[]){

#ifdef HAVE_BTSTACK_STDIN
    int arg = 1;
    cmdline_addr_found = 0;
    
    while (arg < argc) {
        if(!strcmp(argv[arg], "-a") || !strcmp(argv[arg], "--address")){
            arg++;
            cmdline_addr_found = sscanf_bd_addr(argv[arg], cmdline_addr);
            arg++;
            if (!cmdline_addr_found) exit(1);
            continue;
        }
        usage(argv[0]);
        return 0;
    }
#else
    (void)argc;
    (void)argv;
#endif

    l2cap_init();

    // Initialize GATT client 
    gatt_client_init();

    sm_init();
    sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);

    hci_event_callback_registration.callback = &packet_handler;
    hci_add_event_handler(&hci_event_callback_registration);

    btstack_stdin_setup(stdin_process);

    // turn on!
    hci_power_control(HCI_POWER_ON);

    return 0;
}

//l2cap初始化
l2cap_init();

//gatt client 初始化
gatt_client_init();

//安全管理模块初始化
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);

这些先不具体分析,后面的章节再详细介绍,先主要分析下:

// turn on!
hci_power_control(HCI_POWER_ON); 

 hci_power_control根据hci_stack->state的值进入相应的分支,当前hci_stack->state = HCI_STATE_OFF,所以执行如下:

int hci_power_control(HCI_POWER_MODE power_mode){
    
    log_info("hci_power_control: %d, current mode %u", power_mode, hci_stack->state);
    
    int err = 0;
    switch (hci_stack->state){
            
        case HCI_STATE_OFF:
            switch (power_mode){
                case HCI_POWER_ON:
                    err = hci_power_control_on();
                    if (err) {
                        log_error("hci_power_control_on() error %d", err);
                        return err;
                    }
                    hci_power_transition_to_initializing();
                    break;
                case HCI_POWER_OFF:
                    // do nothing
                    break;  
                case HCI_POWER_SLEEP:
                    // do nothing (with SLEEP == OFF)
                    break;
            }
            break;
        ...
    }

    // create internal event
    hci_emit_state();
    
    // trigger next/first action
    hci_run();
	
    return 0;
}

上述过程中,usb被重新打开:
hci_power_control_on();
    hci_stack->hci_transport->init(hci_stack->config);
    hci_stack->hci_transport->open();

hci_stack相关状态设置:
hci_power_transition_to_initializing();
    hci_stack->state = HCI_STATE_INITIALIZING;
    hci_stack->substate = HCI_INIT_SEND_RESET;

创建内部事件:
hci_emit_state();
    event[0] = BTSTACK_EVENT_STATE;    // BTSTACK_EVENT_STATE = 0x60
    event[1] = sizeof(event) - 2;
    event[2] = hci_stack->state;
    hci_emit_event(event, sizeof(event), 1);

    btstack_linked_list_iterator_init(&it, &hci_stack->event_handlers);
    while (btstack_linked_list_iterator_has_next(&it)){
        btstack_packet_callback_registration_t * entry =     (btstack_packet_callback_registration_t*) btstack_linked_list_iterator_next(&it);
        entry->callback(HCI_EVENT_PACKET, 0, event, size);    //HCI_EVENT_PACKET = 0x04
    }

运行
// trigger next/first action
hci_run();

乱花渐欲迷人眼,先来看看我军的摆兵布阵(要画正确,画好挺难得!/(ㄒoㄒ)/~~):

hci_run是根据hci_stack结构体的各种状态值条件执行的,在运行hci_run()之前,hci_stack主要的状态值如下:

hci_stack->state = HCI_STATE_INITIALIZING;
hci_stack->substate = HCI_INIT_SEND_RESET;

hci_run函数非常长,它根据hci_stack各个状态值选择执行不同的流程,根据当前hci_stack的值,hci_run执行如下:

static void hci_run(void){
    ...
    switch (hci_stack->state){
        case HCI_STATE_INITIALIZING:
            hci_initializing_run();
            break;
        ...
    }
}

hci_initializing_run函数定义如下:

static void hci_initializing_run(void){

    switch (hci_stack->substate){
        case HCI_INIT_SEND_RESET:
            hci_state_reset();
            hci_stack->substate = HCI_INIT_W4_SEND_RESET;
            hci_send_cmd(&hci_reset);
            break;

        case HCI_INIT_SEND_READ_LOCAL_VERSION_INFORMATION:
            hci_send_cmd(&hci_read_local_version_information);
            hci_stack->substate = HCI_INIT_W4_SEND_READ_LOCAL_VERSION_INFORMATION;
            break;

        case HCI_INIT_SEND_READ_LOCAL_NAME:
            hci_send_cmd(&hci_read_local_name);
            hci_stack->substate = HCI_INIT_W4_SEND_READ_LOCAL_NAME;
            break;

        ...

        default:
            return;
    }
}

因为 hci_stack->substate = HCI_INIT_SEND_RESET,所以这里主机发送了软复位命令,并且hci_stack->substate设置为HCI_INIT_W4_SEND_RESET。

之后便是控制器返回响应数据包(事件),导致event_handler被调用,event_handler函数也很长,但很好理解:

static void event_handler(uint8_t *packet, int size){

    switch (hci_event_packet_get_type(packet)) {
        case HCI_EVENT_COMMAND_COMPLETE:
            hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
            
            //判断是否为读取本地名的返回数据包
            if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
                if (packet[5]) break;
                // terminate, name 248 chars
                packet[6+248] = 0;
                log_info("local name: %s", &packet[6]);
            }

            //判断是否读取缓存大小的返回数据包
            if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_buffer_size)){
                ...
            }
            
            ...
            break;

        case HCI_EVENT_COMMAND_STATUS:
            ...
            break;

        case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
            ...
            break;

        ...

        default:
            break;
    }

    // handle BT initialization
    if (hci_stack->state == HCI_STATE_INITIALIZING){
        hci_initializing_event_handler(packet, size);
    }

    // help with BT sleep
    if (hci_stack->state == HCI_STATE_FALLING_ASLEEP
        && hci_stack->substate == HCI_FALLING_ASLEEP_W4_WRITE_SCAN_ENABLE
        && HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_scan_enable)){
        hci_initializing_next_state();
    }

    // notify upper stack
    hci_emit_event(packet, size, 0);   // don't dump, already happened in packet handler
    
    // moved here to give upper stack a chance to close down everything with hci_connection_t intact
    if (hci_event_packet_get_type(packet) == HCI_EVENT_DISCONNECTION_COMPLETE){
        if (!packet[2]){
            handle = little_endian_read_16(packet, 3);
            hci_connection_t * aConn = hci_connection_for_handle(handle);
            if (aConn) {
                uint8_t status = aConn->bonding_status;
                uint16_t flags = aConn->bonding_flags;
                bd_addr_t bd_address;
                memcpy(&bd_address, aConn->address, 6);
                hci_shutdown_connection(aConn);
                // connection struct is gone, don't access anymore
                if (flags & BONDING_EMIT_COMPLETE_ON_DISCONNECT){
                    hci_emit_dedicated_bonding_result(bd_address, status);
                }
            }
        }
    }

    // execute main loop
    hci_run();
}

 前面有提到过,对于软复位控制器返回的数据包数据为(0e 04 01 03 0c 00),为HCI_EVENT_COMMAND_COMPLETE通用命令完成事件,所以在上面会进入对应的switch分支(但实际后面不满足条件判断,没有处理),记住此时hci_stack->state为HCI_STATE_INITIALIZING,hci_stack->substate设置为HCI_INIT_W4_SEND_RESET。所以将执行hci_initializing_event_handler(packet, size);

static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){

    if (hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_COMPLETE){
        uint16_t opcode = little_endian_read_16(packet,3);
        if (opcode == hci_stack->last_cmd_opcode){
            command_completed = 1;
        } else {
           
        }
    }

    if (hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_STATUS){
        uint8_t  status = packet[2];
        uint16_t opcode = little_endian_read_16(packet,4);
        if (opcode == hci_stack->last_cmd_opcode){
            if (status){
                command_completed = 1;
            }
        }
    }

    if (!command_completed) return;

    switch(hci_stack->substate){
        case HCI_INIT_W4_SEND_RESET:
            hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS;
            return ;

        case HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS:
            if (need_baud_change &&
              ((hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION) || 
               (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA))) {
                hci_stack->substate = HCI_INIT_SEND_BAUD_CHANGE_BCM;
                return;
            }
            if (need_addr_change){
                hci_stack->substate = HCI_INIT_SET_BD_ADDR;
                return;
            }
            hci_stack->substate = HCI_INIT_READ_BD_ADDR;
            return;

        case HCI_INIT_W4_READ_BD_ADDR:
            // only read buffer size if supported
            if (hci_stack->local_supported_commands[0] & 0x01) {
                hci_stack->substate = HCI_INIT_READ_BUFFER_SIZE;
                return;
            }
            // skipping read buffer size
            hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_FEATURES;
            return;

        case HCI_INIT_W4_SET_EVENT_MASK:
            // skip Classic init commands for LE only chipsets
            if (!hci_classic_supported()){
#ifdef ENABLE_BLE
                if (hci_le_supported()){
                    hci_stack->substate = HCI_INIT_LE_READ_BUFFER_SIZE; // skip all classic command
                    return;
                }
#endif
                log_error("Neither BR/EDR nor LE supported");
                hci_init_done();
                return;
            }
            if (!gap_ssp_supported()){
                hci_stack->substate = HCI_INIT_WRITE_PAGE_TIMEOUT;
                return;
            }
            break;

#ifdef ENABLE_BLE            
        case HCI_INIT_W4_LE_READ_BUFFER_SIZE:
            // skip write le host if not supported (e.g. on LE only EM9301)
            if (hci_stack->local_supported_commands[0] & 0x02) break;
            hci_stack->substate = HCI_INIT_LE_SET_EVENT_MASK;
            return;

#ifdef ENABLE_LE_DATA_LENGTH_EXTENSION
        case HCI_INIT_W4_WRITE_LE_HOST_SUPPORTED:
            log_info("Supported commands %x", hci_stack->local_supported_commands[0] & 0x30);
            if ((hci_stack->local_supported_commands[0] & 0x30) == 0x30){
                hci_stack->substate = HCI_INIT_LE_SET_EVENT_MASK;
                return;
            }
            // explicit fall through to reduce repetitions

#ifdef ENABLE_LE_CENTRAL
            hci_stack->substate = HCI_INIT_READ_WHITE_LIST_SIZE;
#else
            hci_init_done();
#endif
            return;
#endif  /* ENABLE_LE_DATA_LENGTH_EXTENSION */

#endif  /* ENABLE_BLE */

// avoid compile error due to duplicate cases: HCI_INIT_W4_BCM_WRITE_SCO_PCM_INT == HCI_INIT_DONE-1
#if defined(ENABLE_BLE) || defined(ENABLE_LE_DATA_LENGTH_EXTENSION) || defined(ENABLE_LE_CENTRAL)
        // Response to command before init done state -> init done
        case (HCI_INIT_DONE-1):
            hci_init_done();
            return;
#endif
            
        default:
            break;
    }
    hci_initializing_next_state();
}
static void hci_initializing_next_state(void){
    hci_stack->substate = (hci_substate_t )( ((int) hci_stack->substate) + 1);
}

控制器正常返回的情况下,hci_stack->substate设置为HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS。

回到前面event_handler将继续向下执行,将执行:

hci_emit_event(packet, size, 0);

之后又是:

hci_run();    // hci_stack->state == HCI_STATE_INITIALIZING
    ...
    hci_initializing_run();    // hci_stack->substate == HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS
        hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
        hci_send_cmd(&hci_read_local_supported_commands);

就这样,主机会像控制器发送一系列的初始化命令,直到初始化完成,然后将hci_stack->state设置为HCI_STATE_WORKING。

event_handler
    hci_initializing_event_handler
        //完成必要的初始化设置后,就可以结束初始化
        hci_init_done();

发布了18 篇原创文章 · 获赞 6 · 访问量 6353

猜你喜欢

转载自blog.csdn.net/lewanhah01/article/details/104029135
今日推荐