蓝牙之五-bludroid协议栈和厂商代码的交互

来源:互联网 发布:hbuilder下载 mac 编辑:程序博客网 时间:2024/04/30 10:21

协议栈和厂商代码交互

完整的蓝牙调用图

这里写图片描述
协议栈所在的目录是/system/bt;厂商代码所在的目录是hardware/broadcom/libbt。
这两个不同的目录反应的是协议栈和厂商固件的交互流程,它们通过hci层进行交互,在bluez时代hci层是在linux kernel实现的,bluedroid时代放在了android层实现。两者交互的主要目录是system/bt/hci。

</system/bt/hci/src/vendor.c>static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";​static const char *VENDOR_LIBRARY_SYMBOL_NAME = "BLUETOOTH_VENDOR_LIB_INTERFACE"; 46 static bool vendor_open( 47     const uint8_t *local_bdaddr, 48     const hci_t *hci_interface) { 49   assert(lib_handle == NULL); 50   hci = hci_interface; 51  52   lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW); 53   if (!lib_handle) { 54     LOG_ERROR("%s unable to open %s: %s", __func__, VENDOR_LIBRARY_NAME, dlerror()); 55     goto error; 56   } 57  58   lib_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME); 59   if (!lib_interface) { 60     LOG_ERROR("%s unable to find symbol %s in %s: %s", __func__, VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror()); 61     goto error; 62   } 63  64   LOG_INFO("alloc value %p", lib_callbacks.alloc); 65  66   int status = lib_interface->init(&lib_callbacks, (unsigned char *)local_bdaddr); 67   if (status) { 68     LOG_ERROR("%s unable to initialize vendor library: %d", __func__, status); 69     goto error; 70   } 71  72   return true; 73  74 error:; 75   lib_interface = NULL; 76   if (lib_handle) 77     dlclose(lib_handle); 78   lib_handle = NULL; 79   return false; 80 }

libbt-vendor是hardware/broadcom/libbt目录下编译出来的。
这里写图片描述
58行在这个库里查找BLUETOOTH_VENDOR_LIB_INTERFACE interface也即BLUETOOTH_VENDOR_LIB_INTERFACE。这个符号定义于hardware/broadcom/libbt/src/bt_vendor_brcm.c
这里写图片描述
init初始化蓝牙使用的串口设备号,
upio_init是io控制初始化,
vnd_load_conf加载蓝牙配置文件(/etc/bluetooth/bt_vendor.conf),

 ​ bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;

将传递进来的函数指针集赋给bt_vendor_cbacks,该集合具有的方法如下。lib_callbacks定义了若干回调函数。

 ​static const bt_vendor_callbacks_t lib_callbacks = {  sizeof(lib_callbacks),  firmware_config_cb,  sco_config_cb,  low_power_mode_cb,  sco_audiostate_cb,  buffer_alloc_cb,  buffer_free_cb,  transmit_cb,  epilog_cb};
 ​memcpy(vnd_local_bd_addr, local_bdaddr, 6);

将本地的6字节蓝牙设备地址赋值到vnd_local_bd_addr里。init,op以及cleanup函数如下。

<hardware/broadcom/libbt/src/bt_vendor_brcm.c> 92 static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr) 93 {...115     userial_vendor_init();116     upio_init();117 118     vnd_load_conf(VENDOR_LIB_CONF_FILE);119 120     /* store reference to user callbacks */121     bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;122 123     /* This is handed over from the stack */124     memcpy(vnd_local_bd_addr, local_bdaddr, 6);125 126     return 0;127 }131 static int op(bt_vendor_opcode_t opcode, void *param)132 {133     int retval = 0;134 135     BTVNDDBG("op for %d", opcode);136 137     switch(opcode)138     {139         case BT_VND_OP_POWER_CTRL:140             {141                 int *state = (int *) param;142                 if (*state == BT_VND_PWR_OFF)143                     upio_set_bluetooth_power(UPIO_BT_POWER_OFF);144                 else if (*state == BT_VND_PWR_ON)145                     upio_set_bluetooth_power(UPIO_BT_POWER_ON);146             }147             break;148 149         case BT_VND_OP_FW_CFG:150             {151                 hw_config_start();152             }153             break;154 155         case BT_VND_OP_SCO_CFG:156             {157 #if (SCO_CFG_INCLUDED == TRUE)158                 hw_sco_config();159 #else160                 retval = -1;161 #endif162             }163             break;164 165         case BT_VND_OP_USERIAL_OPEN:166             {167                 int (*fd_array)[] = (int (*)[]) param;168                 int fd, idx;169                 fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);170                 if (fd != -1)171                 {172                     for (idx=0; idx < CH_MAX; idx++)173                         (*fd_array)[idx] = fd;174 175                     retval = 1;176                 }177                 /* retval contains numbers of open fd of HCI channels */178             }179             break;180 181         case BT_VND_OP_USERIAL_CLOSE:182             {183                 userial_vendor_close();184             }185             break;186 187         case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:188             {189                 uint32_t *timeout_ms = (uint32_t *) param;190                 *timeout_ms = hw_lpm_get_idle_timeout();191             }192             break;193 194         case BT_VND_OP_LPM_SET_MODE:195             {196                 uint8_t *mode = (uint8_t *) param;197                 retval = hw_lpm_enable(*mode);198             }199             break;200 201         case BT_VND_OP_LPM_WAKE_SET_STATE:202             {203                 uint8_t *state = (uint8_t *) param;204                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \205                                         TRUE : FALSE;206 207                 hw_lpm_set_wake_state(wake_assert);208             }209             break;210 211          case BT_VND_OP_SET_AUDIO_STATE:212             {213                 retval = hw_set_audio_state((bt_vendor_op_audio_state_t *)param);214             }215             break;216 217         case BT_VND_OP_EPILOG:218             {219 #if (HW_END_WITH_HCI_RESET == FALSE)220                 if (bt_vendor_cbacks)221                 {222                     bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);223                 }224 #else225                 hw_epilog_process();226 #endif227             }228             break;229     }230 231     return retval;232 }233 234 /** Closes the interface */235 static void cleanup( void )236 {237     BTVNDDBG("cleanup");238 239     upio_cleanup();240 241     bt_vendor_cbacks = NULL;242 }​245 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {246     sizeof(bt_vendor_interface_t),247     init,248     op,249     cleanup250 };

op函数定义了博通给的若干命令和命令参数接口,如:

 ​        case BT_VND_OP_POWER_CTRL:            {                int *state = (int *) param;                if (*state == BT_VND_PWR_OFF)                    upio_set_bluetooth_power(UPIO_BT_POWER_OFF);                else if (*state == BT_VND_PWR_ON)                    upio_set_bluetooth_power(UPIO_BT_POWER_ON);            }            break;

该命令是蓝牙模块电源控制命令,根据参数值决定IO管脚是上拉还是下拉来管理设备上下电。底层实现是读写rfkill目录。操作码的op函数的使用方法和init类似,在同一个文件目录。如:

<system/bt/hci/src/vendor.c> ​static int send_command(vendor_opcode_t opcode, void *param) {  assert(lib_interface != NULL);  return lib_interface->op(opcode, param);}

接下来协议栈向上层

vendor_open是如何被调用的?又是谁调用的?

 <​system/bt/hci/src/vendor.c>static const vendor_t interface = {  vendor_open,  vendor_close,  send_command,  send_async_command,  set_callback,};const vendor_t *vendor_get_interface() {  buffer_allocator = buffer_allocator_get_interface();  return &interface;}

vendor_open做为了interface的函数指针集,而调用vendor_get_interface就会返回该interface。查了下协议栈下调用该接口的源码,调用的地方如下:

< system/bt/>hci/src/hci_hal_h4.c:255:  vendor = vendor_get_interface();hci/src/hci_layer.c:782:  vendor = vendor_get_interface();hci/src/low_power_manager.c:236:  vendor = vendor_get_interface();hci/src/hci_hal_mct.c:202:  vendor = vendor_get_interface();

实际上vendor_open会被hci_hal_h4.c和hci_layer.c调用。

<system/bt/hci/src/hci_hal_h4.c> ​254 const hci_hal_t *hci_hal_h4_get_interface() {255   vendor = vendor_get_interface();256   return &interface;257 }<system/bt/hci/src/hci_hal.c>const hci_hal_t *hci_hal_get_interface() {#if HCI_USE_MCT  return hci_hal_mct_get_interface();#else  return hci_hal_h4_get_interface();#endif}<system/bt/hci/src/hci_layer.c>const hci_t *hci_layer_get_interface() {  buffer_allocator = buffer_allocator_get_interface();  hal = hci_hal_get_interface();  btsnoop = btsnoop_get_interface();  hci_inject = hci_inject_get_interface();  packet_fragmenter = packet_fragmenter_get_interface();  vendor = vendor_get_interface();  low_power_manager = low_power_manager_get_interface();  init_layer_interface();  return &interface;}

hci_hal_get_interface();
vendor = vendor_get_interface();
上述函数被system/bt/main/bte_main.c调用。

 ​void bte_main_boot_entry(void){    module_init(get_module(GKI_MODULE));    module_init(get_module(COUNTER_MODULE));    hci = hci_layer_get_interface();    if (!hci)      LOG_ERROR("%s could not get hci layer interface.", __func__);    btu_hci_msg_queue = fixed_queue_new(SIZE_MAX);    if (btu_hci_msg_queue == NULL) {      LOG_ERROR("%s unable to allocate hci message queue.", __func__);      return;    }    data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);    hci->set_data_queue(btu_hci_msg_queue);#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))    bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);#endif    module_init(get_module(STACK_CONFIG_MODULE));}

这一过程如下。
这里写图片描述
附,协议栈几个目录作用:
Bluetooth Embedded System(BTE),它实现了BT的核心功能。
Bluetooth Application Layer (BTA),用于和android framework层交互。
BTI F: Bluetooth Interface
BTU : Bluetooth Upper Layer
BTM: Bluetooth Manager
BT 系统服务通过JNI与BT stack交互,并且通过Binder IPC通信与应用交互。这个系统服务同时也提供给RD获取不同的BT profiles。
GKI以库libbt-brcm_gki.so(Static Lib?)的形式提供给BlueDroid使用,该层是一个适配层,适配了OS相关的进程、内存相关的管理,还可以用于线程间传递消息主要通过变量gki_cb实现对进程的统一管理。

0 0
原创粉丝点击