历史的帷幕徐徐落下,新的时代即将到来,从此人类踏入了新纪元...
在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();