蓝牙之五-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实现对进程的统一管理。
- 蓝牙之五-bludroid协议栈和厂商代码的交互
- Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比)
- Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比) .
- Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比)
- 关于蓝牙芯片及其领导厂商的简介和分析
- 飞信分析之五:用即时消息聊天时的协议交互过程
- 蓝牙的进阶之路-扫描.链接.数据传输.手机和硬件的交互(一)
- 探讨蓝牙协议栈的原理和结构
- 探讨蓝牙协议栈的原理和结构
- 探讨蓝牙协议栈的原理和结构
- BlueTooth: 蓝牙协议栈的原理和结构
- BlueTooth: 蓝牙协议栈的原理和结构
- BlueTooth: 蓝牙协议栈的原理和结构
- 蓝牙笔和手机通过蓝牙协议的通讯
- 蓝牙协议的命令和事件
- 蓝牙协议的命令和事件
- 蓝牙协议的命令和事件
- 蓝牙协议的命令和事件
- ThinkPHP实现数据的创建
- 1.Android如何实现相机功能... 2.如何实现音频的录制... 3.如何实现视频的录制..
- 利用 find 和 crontab 命令清理过期文件
- Decorating Pattern
- 人生不应该让自己感到遗憾
- 蓝牙之五-bludroid协议栈和厂商代码的交互
- jquery的.fn.extend使用方法
- python番外(1)——matplotlib中文显示问题
- bzoj2768(最小割,二者取其一式问题)
- HDU 5781 ATM Mechine(概率DP求期望)
- ReactiveCocoa信号使用方法
- 解MPU6050,用STM32读取原始数据,并相互融合算出俯仰角、翻滚角、偏航角
- POJ1815
- MySql 5.7.13解压版安装和出现的一些问题