主函数分析(port/windows-winusb/main.c):
int main(int argc, const char * argv[])
{
main_argc = argc;
main_argv = argv;
btstack_memory_init();
...
#if MAX_NR_HCI_CONNECTIONS > 0
//把hci_connection_storage挂到hci_connection_pool单向链表下,hci_connection_storage是hci_connection_t类型数组,MAX_NR_HCI_CONNECTIONS是数组个数
btstack_memory_pool_create(&hci_connection_pool, hci_connection_storage, MAX_NR_HCI_CONNECTIONS, sizeof(hci_connection_t));
#endif
...
#if MAX_NR_GATT_CLIENTS > 0
btstack_memory_pool_create(&gatt_client_pool, gatt_client_storage, MAX_NR_GATT_CLIENTS, sizeof(gatt_client_t));
#endif
...
btstack_run_loop_init(btstack_run_loop_windows_get_instance());
the_run_loop = btstack_run_loop_windows;
the_run_loop->init();
/*
btstack_run_loop_windows定义为如下:
static const btstack_run_loop_t btstack_run_loop_windows = {
&btstack_run_loop_windows_init,
&btstack_run_loop_windows_add_data_source,
&btstack_run_loop_windows_remove_data_source,
&btstack_run_loop_windows_enable_data_source_callbacks,
&btstack_run_loop_windows_disable_data_source_callbacks,
&btstack_run_loop_windows_set_timer,
&btstack_run_loop_windows_add_timer,
&btstack_run_loop_windows_remove_timer,
&btstack_run_loop_windows_execute,
&btstack_run_loop_windows_dump_timer,
&btstack_run_loop_windows_get_time_ms,
};
*/
// setup USB Transport
transport = hci_transport_usb_instance();
transport = hci_transport_usb
/*
hci_transport_usb定义为如下:
// get usb singleton
static const hci_transport_t hci_transport_usb = {
/* const char * name; */ "H2_WINUSB",
/* void (*init) (const void *transport_config); */ &usb_init,
/* int (*open)(void); */ &usb_open,
/* int (*close)(void); */ &usb_close,
/* void (*register_packet_handler)(void (*handler)(...); */ &usb_register_packet_handler,
/* int (*can_send_packet_now)(uint8_t packet_type); */ &usb_can_send_packet_now,
/* int (*send_packet)(...); */ &usb_send_packet,
/* int (*set_baudrate)(uint32_t baudrate); */ NULL,
/* void (*reset_link)(void); */ NULL,
#ifdef ENABLE_SCO_OVER_HCI
/* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ usb_set_sco_config,
#else
/* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
#endif
};
*/
btstack_chipset_intel_download_firmware(hci_transport_usb, &intel_firmware_done);
done = intel_firmware_done;
transport = hci_transport_usb;
transport->register_packet_handler(&transport_packet_handler);
transport->open();
//这里,主机往控制器发送复位CMD
state = 0;
state_machine(NULL);
btstack_run_loop_execute();
the_run_loop->execute();
}
1、把结构体btstack_run_loop_windows赋值the_run_loop全局变量(btstack_run_loop_windows基于windows平台实现的操作接口),并调用了btstack_run_loop_windows的init函数;
the_run_loop = btstack_run_loop_windows;
//btstack_run_loop_windows定义如下:
static const btstack_run_loop_t btstack_run_loop_windows = {
&btstack_run_loop_windows_init,
&btstack_run_loop_windows_add_data_source,
&btstack_run_loop_windows_remove_data_source,
&btstack_run_loop_windows_enable_data_source_callbacks,
&btstack_run_loop_windows_disable_data_source_callbacks,
&btstack_run_loop_windows_set_timer,
&btstack_run_loop_windows_add_timer,
&btstack_run_loop_windows_remove_timer,
&btstack_run_loop_windows_execute,
&btstack_run_loop_windows_dump_timer,
&btstack_run_loop_windows_get_time_ms,
};
2、设置transport 全局变量(hci_transport_usb是用于操作usb的结构体);
transport = hci_transport_usb;
//hci_transport_usb定义如下:
static const hci_transport_t hci_transport_usb = {
/* const char * name; */ "H2_WINUSB",
/* void (*init) (const void *transport_config); */ &usb_init,
/* int (*open)(void); */ &usb_open,
/* int (*close)(void); */ &usb_close,
/* void (*register_packet_handler)(void (*handler)(...); */ &usb_register_packet_handler,
/* int (*can_send_packet_now)(uint8_t packet_type); */ &usb_can_send_packet_now,
/* int (*send_packet)(...); */ &usb_send_packet,
/* int (*set_baudrate)(uint32_t baudrate); */ NULL,
/* void (*reset_link)(void); */ NULL,
#ifdef ENABLE_SCO_OVER_HCI
/* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ usb_set_sco_config,
#else
/* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
#endif
};
3、调用btstack_chipset_intel_download_firmware函数,执行了如下操作;
//设置done全局变量,done为函数指针变量,赋值intel_firmware_done,该函数启动真正的上层应用
done = intel_firmware_done;//把usb操作抽象出的结构体hci_transport_usb赋值给全局变量transport
transport = hci_transport_usb;
//调用hci_transport_usb的register_packet_handler注册回调函数,到数据包到达时调用transport_packet_handler
transport->register_packet_handler(&transport_packet_handler);
//调用usb的open函数,打开usb设备,并注册了数据处理对象struct btstack_data_source到data_sources
transport->open();//下面两句语句会导致Host向Controller发送复位命令,数据传输从此开始
state = 0;
state_machine(NULL);
上面transport->register_packet_handler(&transport_packet_handler)注册回调函数,作为参数传入的transport_packet_handler函数定义如下:
static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
UNUSED(packet_type);
// we also get events with packet_type ACL from the controller
hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
switch (hci_event_packet_get_type(packet)){
case HCI_EVENT_COMMAND_COMPLETE:
case HCI_EVENT_VENDOR_SPECIFIC:
state_machine(packet);
break;
default:
break;
}
}
4、btstack_run_loop_execute中调用循环处理函数,其实就是调用btstack_run_loop_windows_execute;
在函数btstack_run_loop_execute中运行的the_run_loop->execute(),其定义如下:
static void btstack_run_loop_windows_execute(void) {
btstack_timer_source_t *ts;
btstack_linked_list_iterator_t it;
while (1) {
// collect handles to wait for
HANDLE handles[100];
memset(handles, 0, sizeof(handles));
int num_handles = 0;
btstack_linked_list_iterator_init(&it, &data_sources);
while (btstack_linked_list_iterator_has_next(&it)){
btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
if (ds->source.handle == 0) continue;
if (ds->flags & (DATA_SOURCE_CALLBACK_READ | DATA_SOURCE_CALLBACK_WRITE)){
handles[num_handles++] = ds->source.handle;
log_debug("btstack_run_loop_execute adding handle %p", ds->source.handle);
}
}
// get next timeout
int32_t timeout_ms = INFINITE;
if (timers) {
ts = (btstack_timer_source_t *) timers;
uint32_t now_ms = btstack_run_loop_windows_get_time_ms();
timeout_ms = ts->timeout - now_ms;
if (timeout_ms < 0){
timeout_ms = 0;
}
log_debug("btstack_run_loop_execute next timeout in %u ms", timeout_ms);
}
int res;
if (num_handles){
// wait for ready Events or timeout
res = WaitForMultipleObjects(num_handles, &handles[0], 0, timeout_ms);
} else {
// just wait for timeout
Sleep(timeout_ms);
res = WAIT_TIMEOUT;
}
// process data source
if (WAIT_OBJECT_0 <= res && res < (WAIT_OBJECT_0 + num_handles)){
void * triggered_handle = handles[res - WAIT_OBJECT_0];
btstack_linked_list_iterator_init(&it, &data_sources);
while (btstack_linked_list_iterator_has_next(&it)){
btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
log_debug("btstack_run_loop_windows_execute: check ds %p with handle %p\n", ds, ds->source.handle);
if (triggered_handle == ds->source.handle){
if (ds->flags & DATA_SOURCE_CALLBACK_READ){
log_debug("btstack_run_loop_windows_execute: process read ds %p with handle %p\n", ds, ds->source.handle);
ds->process(ds, DATA_SOURCE_CALLBACK_READ);
} else if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){
log_debug("btstack_run_loop_windows_execute: process write ds %p with handle %p\n", ds, ds->source.handle);
ds->process(ds, DATA_SOURCE_CALLBACK_WRITE);
}
break;
}
}
}
// process timers
uint32_t now_ms = btstack_run_loop_windows_get_time_ms();
while (timers) {
ts = (btstack_timer_source_t *) timers;
if (ts->timeout > now_ms) break;
log_debug("btstack_run_loop_windows_execute: process timer %p\n", ts);
// remove timer before processing it to allow handler to re-register with run loop
btstack_run_loop_windows_remove_timer(ts);
ts->process(ts);
}
}
}
btstack_run_loop_execute的工作可总结为如下:
循环遍历data_sources,把挂到链表的所有struct btstack_data_source结构体实例的handle成员保存到数组handles中;
调用WaitForMultipleObjects(参数为handles数组和超时时间),等待事件或超时,该函数类似于linux的select函数;
当有事件发生或者超时,遍历data_sources链表中的struct btstack_data_source结构体实例,找到产生event的实例,调用其process回调函数;
如果设置了超时处理并且超时发生,则当调用struct btstack_timer_source结构体实例的process回调函数;
循环上述过程...
可知btstack_run_loop_windows_execute和 data_sources密切相关,在while循环里面取得data_sources链表的成员调用。那data_sources的成员由哪里加入链表呢?通过下面的接口:
static void btstack_run_loop_windows_add_data_source(btstack_data_source_t *ds);
btstack_run_loop_windows_add_data_source函数调用流程如下:
usb_open (hci_transport_h2_winusb.c)
{
...
usb_try_open_device();
...
// setup btstack data soures
usb_data_source_event_in.source.handle = usb_overlapped_event_in.hEvent;
btstack_run_loop_set_data_source_handler(&usb_data_source_event_in, &usb_process_event_in);
btstack_run_loop_add_data_source(&usb_data_source_event_in);usb_data_source_command_out.source.handle = usb_overlapped_command_out.hEvent;
btstack_run_loop_set_data_source_handler(&usb_data_source_command_out, &usb_process_command_out);
btstack_run_loop_add_data_source(&usb_data_source_command_out);usb_data_source_acl_in.source.handle = usb_overlapped_acl_in.hEvent;
btstack_run_loop_set_data_source_handler(&usb_data_source_acl_in, &usb_process_acl_in);
btstack_run_loop_add_data_source(&usb_data_source_acl_in);usb_data_source_acl_out.source.handle = usb_overlapped_acl_out.hEvent;
btstack_run_loop_set_data_source_handler(&usb_data_source_acl_out, &usb_process_acl_out);
btstack_run_loop_add_data_source(&usb_data_source_acl_out);
...}
如上可知在 transport->open()时调用了btstack_run_loop_add_data_source,把struct btstack_data_source结构体实例挂到data_sources链表下;
上面提到的struct btstack_data_source结构体定义如下:
typedef struct btstack_data_source {
// linked item
btstack_linked_item_t item;
// item to watch in run loop
union {
// file descriptor for posix systems
int fd;
// handle on windows
void * handle;
} source; //windows的WaitForMultipleObjects接口通过handle/fd等待事件产生
// callback to call for enabled callback types
//btstack_run_loop_windows_execute中事件产生后回调process
void (*process)(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type);
// flags storing enabled callback types
uint16_t flags;
} btstack_data_source_t;
数据的通讯方Host、Controller之间,对于BLE,有如下几种数据的传输:
command (Host -> Controller)
event (Controller -> Host)
acl_out (Host -> Controller)
acl_in (Controller -> Host)
目前作为Host端为什么还有usb_data_source_command_out、usb_data_source_acl_out?不是接收到Controller的数据才产生事件吗?原因是为了通知上层command和acl data已经发送完成,可以继续发送,所以发送完成后也加入事件触发。
触发流程是这样的(以command为例,acl_out 也一样):
usb_send_packet(hci_transport_h2_winusb.c)
usb_send_cmd_packet(packet, size);
//传输完成时触发usb_overlapped_command_out的事件
WinUsb_ControlTransfer(usb_interface_0_handle, setup_packet, packet, size, NULL, &usb_overlapped_command_out);
总结一下
1. transport->open();打开usb设备,并往data_sources链入struct btstack_data_source结构体对象(针对command、event 、acl data,acl data包括acl in 和 acl out)
2. state = 0; state_machine(NULL);Host向Controller发送复位命令,Host与Controller交互开始,随后Controller返回event
3. btstack_run_loop_execute();遍历data_sources中的struct btstack_data_source结构体对象,等待事件产生,调用struct btstack_data_source结构体对象的process函数。此步循环进行