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


协议栈和厂商代码交互

完整的蓝牙调用图

这里写图片描述
协议栈所在的目录是/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 #else
160 retval = -1;
161 #endif
162 }
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 #else
225 hw_epilog_process();
226 #endif
227 }
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 cleanup
250 };

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实现对进程的统一管理。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com