蓝牙扫描过程是指扫描蓝牙设备
这里有两张截图
第一张图显示的是安卓设置setting菜单栏中有Bluetooth这一项,点进去以后,点击右上角显示如下的截图。
其中Refresh就是刷新设备列表,也就会扫描设备信息。
上图显示的三个菜单在BluetoothSettings.java文件。
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mLocalAdapter == null) return;
// If the user is not allowed to configure bluetooth, do not show the menu.
if (isUiRestricted()) return;
boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
boolean isDiscovering = mLocalAdapter.isDiscovering();
int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
R.string.bluetooth_search_for_devices;
menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
.setEnabled(bluetoothIsEnabled && !isDiscovering)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
.setEnabled(bluetoothIsEnabled)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
super.onCreateOptionsMenu(menu, inflater);
}
当选择了Refresh项后,会触发如下操作:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ID_SCAN:
if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
MetricsLogger.action(getActivity(), MetricsLogger.ACTION_BLUETOOTH_SCAN);
startScanning();
}
return true;
private void startScanning() {
if (!mAvailableDevicesCategoryIsPresent) {
getPreferenceScreen().addPreference(mAvailableDevicesCategory);
mAvailableDevicesCategoryIsPresent = true;
}
...
mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
mAvailableDevicesCategory.removeAll();
mInitialScanStarted = true;
mLocalAdapter.startScanning(true);
}
实际上调用了在frameworks层的一个BTlib实现相关功能;
public void startScanning(boolean force) {
// Only start if we're not already scanning
if (!mAdapter.isDiscovering()) {
if (!force) {
// Don't scan more than frequently than SCAN_EXPIRATION_MS,
// unless forced
if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {
return;
}
// If we are playing music, don't scan unless forced.
A2dpProfile a2dp = mProfileManager.getA2dpProfile();
if (a2dp != null && a2dp.isA2dpPlaying()) {
return;
}
}
if (mAdapter.startDiscovery()) {
mLastScan = System.currentTimeMillis();
}
}
}
首先要求权限Manifest.permission.BLUETOOTH_ADMIN。
private IBluetooth mService;
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startDiscovery() {
if (getState() != STATE_ON) return false;
try {
synchronized(mManagerCallback) {
if (mService != null) return mService.startDiscovery();
}
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
mService用binder调用startDiscovery。
public class AdapterService extends Service {
...
private static class AdapterServiceBinder extends IBluetooth.Stub {
private AdapterService mService;
public boolean startDiscovery() {
if (!Utils.checkCaller()) {
Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
return false;
}
AdapterService service = getService();
if (service == null) return false;
return service.startDiscovery();
}
...}
boolean startDiscovery() {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
return startDiscoveryNative();
}
}
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
ALOGV("%s:",__FUNCTION__);
jboolean result = JNI_FALSE;
if (!sBluetoothInterface) return result;
int ret = sBluetoothInterface->start_discovery();
result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
return result;
}
sBluetoothInterface是bluetooth.default.so的接口,在前篇文章中有该接口对应方法所在的位置。
所在目录是/system/bt/,
再次把协议栈使用的简称再罗列一遍:
BTE(bluetooth embedded system):实现BT核心功能
BTA(bluetooth application layer):用于和android frameworks交流。
BTIF(bluetooth interface):dm(device management)
BTU(bluetooth upperlayer)
BTM(bluetooth manager)
static int start_discovery(void)
{
/* sanity check */
if (interface_ready() == FALSE)
return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
btif_dm_start_discovery
扫描分为BR/EDR类型的设备和BLE类型的设备。
BR/EDR类型设备扫描参数存在tBTA_DM_INQ结构体里,参数如下:
查询模式(general or limited),
查询的长(以1.28s为单位,最长1.28*10s),
最大的查询响应量(0表示无限制响应)。
查询过滤类型(清除,按设备类型过滤,按设备地址过滤)。
如果是BLE类型的扫描还有如下参数需要设置一些其它的参数,这里以正常设备扫描流程说明过程。
这里将BR/EDR情况的参数设置罗列如下(dm 是device management简称):
inq_params.mode = BTA_DM_GENERAL_INQUIRY;
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
inq_params.report_dup = TRUE;
inq_params.filter_type = BTA_DM_INQ_CLR;
bt_status_t btif_dm_start_discovery(void)
{
tBTA_DM_INQ inq_params;
tBTA_SERVICE_MASK services = 0;
tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param;
...
inq_params.mode = BTA_DM_GENERAL_INQUIRY;
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
inq_params.report_dup = TRUE;
inq_params.filter_type = BTA_DM_INQ_CLR;
/* TODO: Filter device by BDA needs to be implemented here */
/* Will be enabled to TRUE once inquiry busy level has been received */
btif_dm_inquiry_in_progress = FALSE;
/* find nearby devices */
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
return BT_STATUS_SUCCESS;
}
查找工作不在bta层进行,前面也说了,bta层是用于和framwork对接的,所以通过发送消息给btu层,让btu层完成工作。
void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback)
{
tBTA_DM_API_SEARCH *p_msg;
if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)
{
memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH));
p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
p_msg->services = services;
p_msg->p_cback = p_cback;
p_msg->rs_res = BTA_DM_RS_NONE;
bta_sys_sendmsg(p_msg);
}
}
msg的header是BTA_DM_API_SEARCH_EVT。该消息被放到btu_bta_msg_queue队列。该消息队列的处理函数在注册这个函数可以看出。
fixed_queue_register_dequeue(btu_bta_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_bta_msg_ready,
NULL);
void btu_bta_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
bta_sys_event(p_msg);
}
上述的p_msg是workqueue中的message。
void bta_sys_event(BT_HDR *p_msg)
{
UINT8 id;
BOOLEAN freebuf = TRUE;
APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);
/* get subsystem id from event */
id = (UINT8) (p_msg->event >> 8);
/* verify id and call subsystem event handler */
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
{
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
}
}
bta_sys_cb是函数指针集,
void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
bta_sys_cb.is_reg[id] = TRUE;
}
这个函数指针的初始化在使能BT时会被初始化到。
static const tBTA_SYS_REG bta_dm_reg =
{
bta_dm_sm_execute,
bta_dm_sm_disable
};
static const tBTA_SYS_REG bta_dm_search_reg =
{
bta_dm_search_sm_execute,
bta_dm_search_sm_disable
};
tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
{
tBTA_DM_API_ENABLE *p_msg;
/* Bluetooth disabling is in progress */
if (bta_dm_cb.disabling)
return BTA_FAILURE;
memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
bta_sys_register (BTA_ID_DM, &bta_dm_reg );
bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
...
}
其调用bta_dm_search_sm_execute处理消息,sm的意思是statemachine,状态机管理穿插在整个蓝牙管理中。
BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
{
tBTA_DM_ST_TBL state_table;
UINT8 action;
int i;
APPL_TRACE_EVENT("bta_dm_search_sm_execute state:%d, event:0x%x",
bta_dm_search_cb.state, p_msg->event);
/* look up the state table for the current state */
state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];
bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];
/* execute action functions */
for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)
{
if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)
{
(*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);
}
else
{
break;
}
}
return TRUE;
}
这个函数根据BT所处状态的不同,调用不同的函数。实际上调用的是bta_dm_search_action【0】,也即bta_dm_search_start
/* state table */
const tBTA_DM_ST_TBL bta_dm_search_st_tbl[] = {
bta_dm_search_idle_st_table,
bta_dm_search_search_active_st_table,
bta_dm_search_search_cancelling_st_table,
bta_dm_search_disc_active_st_table
};
这里忽略BLE情况。
void bta_dm_search_start (tBTA_DM_MSG *p_data)
{
tBTM_INQUIRY_CMPL result;
APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__, p_bta_dm_cfg->avoid_scatter);
if (p_bta_dm_cfg->avoid_scatter &&
(p_data->search.rs_res == BTA_DM_RS_NONE) && bta_dm_check_av(BTA_DM_API_SEARCH_EVT))
{
memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
return;
}
BTM_ClearInqDb(NULL);//清楚查询的db(database)
/* save search params */
bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
bta_dm_search_cb.services = p_data->search.services;
result.status = BTM_StartInquiry( (tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb,
(tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
if (result.status != BTM_CMD_STARTED)
{
result.num_resp = 0;
bta_dm_inq_cmpl_cb ((void *)&result);
}
}
BTM_StartInquiry中的第一个参数中inq_params,也就是btif_dm_start_discovery发送的参数。
这个函数的查询过程包括BLE和BR/EDR两种模式的查询。重点还是BR/EDR模式。
tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
tBTM_CMPL_CB *p_cmpl_cb)
{
tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_API ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
p_inqparms->filter_cond_type);
/* Only one active inquiry is allowed in this implementation.
Also do not allow an inquiry if the inquiry filter is being updated */
if (p_inq->inq_active || p_inq->inqfilt_active)
{
{
return (BTM_BUSY);
BTM_TRACE_API("BTM_StartInquiry: return BUSY");
}
}
else
p_inq->scan_type = INQ_GENERAL;
/*** Make sure the device is ready ***/
if (!BTM_IsDeviceUp())
return (BTM_WRONG_MODE);
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
)
return (BTM_ILLEGAL_VALUE);
/* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;
p_inq->p_inq_cmpl_cb = p_cmpl_cb;
p_inq->p_inq_results_cb = p_results_cb;
p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
p_inq->inq_active = p_inqparms->mode;
BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
/* start LE inquiry here if requested */
#if BLE_INCLUDED == TRUE
if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
&&(p_inq->next_state==BTM_BLE_ONE || p_inq->next_state==BTM_BLE_TWO ||
p_inq->next_state==BTM_NO_INTERLEAVING)
#endif
)
{
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
#endif
if (!controller_get_interface()->supports_ble())
{
p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
status = BTM_ILLEGAL_VALUE;
}
/* BLE for now does not support filter condition for inquiry */
else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
p_inqparms->duration)) != BTM_CMD_STARTED)
{
BTM_TRACE_ERROR("Err Starting LE Inquiry.");
p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
}
#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
#endif
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if(p_inq->next_state==BTM_NO_INTERLEAVING)
{
p_inq->next_state=BTM_FINISH;
}
else
{
BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d",
p_inq->next_state+1);
p_inq->next_state+=1;
}
/* reset next_state if status <> BTM_Started */
if(status!=BTM_CMD_STARTED)
p_inq->next_state=BTM_BR_ONE;
/* if interleave scan..return here */
return status;
#endif
BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
}
#endif /* end of BLE_INCLUDED */
/* we're done with this routine if BR/EDR inquiry is not desired. */
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
return status;
/* BR/EDR inquiry portion */
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if((p_inq->next_state==BTM_BR_ONE || p_inq->next_state==BTM_BR_TWO ||
p_inq->next_state==BTM_NO_INTERLEAVING ))
{
p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
#endif
/* If a filter is specified, then save it for later and clear the current filter.
The setting of the filter is done upon completion of clearing of the previous
filter.
*/
switch (p_inqparms->filter_cond_type)
{
case BTM_CLR_INQUIRY_FILTER:
p_inq->state = BTM_INQ_SET_FILT_STATE;
break;
case BTM_FILTER_COND_DEVICE_CLASS:
case BTM_FILTER_COND_BD_ADDR:
/* The filter is not being used so simply clear it;
the inquiry can start after this operation */
p_inq->state = BTM_INQ_CLR_FILT_STATE;
p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
/* =============>>>> adding LE filtering here ????? */
break;
default:
return (BTM_ILLEGAL_VALUE);
}
/* Before beginning the inquiry the current filter must be cleared, so initiate the command */
if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
&p_inqparms->filter_cond)) != BTM_CMD_STARTED)
p_inq->state = BTM_INQ_INACTIVE_STATE;
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if (p_inq->next_state==BTM_NO_INTERLEAVING)
p_inq->next_state=BTM_FINISH;
else
{
BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
p_inq->next_state+1);
p_inq->next_state+=1;
}
}
if (status!=BTM_CMD_STARTED)
{
/* Some error beginning the scan process.
Reset the next_state parameter.. Do we need to reset the inq_active also?
*/
BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x", status);
p_inq->next_state=BTM_BR_ONE;
}
#endif
return (status);
}
该函数判断是否支持BLE扫描,如果支持调用btm_ble_start_inquiry进行BLE模式扫描,对于BR/EDR模式,则调用btm_set_inq_event_filter进行扫描。
static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
tBTM_INQ_FILT_COND *p_filt_cond)
{
UINT8 condition_length = DEV_CLASS_LEN * 2;
UINT8 condition_buf[DEV_CLASS_LEN * 2];
UINT8 *p_cond = condition_buf; /* points to the condition to pass to HCI */
#if (BTM_INQ_DEBUG == TRUE)
BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
filter_cond_type);
BTM_TRACE_DEBUG (" condition [%02x%02x%02x %02x%02x%02x]",
p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
#endif
/* Load the correct filter condition to pass to the lower layer */
switch (filter_cond_type)
{
case BTM_FILTER_COND_DEVICE_CLASS:
/* copy the device class and device class fields into contiguous memory to send to HCI */
memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
memcpy (&condition_buf[DEV_CLASS_LEN],
p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
/* condition length should already be set as the default */
break;
case BTM_FILTER_COND_BD_ADDR:
p_cond = p_filt_cond->bdaddr_cond;
/* condition length should already be set as the default */
break;
case BTM_CLR_INQUIRY_FILTER:
condition_length = 0;
break;
default:
return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
}
btm_cb.btm_inq_vars.inqfilt_active = TRUE;
/* Filter the inquiry results for the specified condition type and value */
if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
p_cond, condition_length))
return (BTM_CMD_STARTED);
else
return (BTM_NO_RESOURCES);
}
这个函数根据条件设置查询的过滤项。
LOCAL_BR_EDR_CONTROLLER_ID选定扫描使用的BT主机控制器。
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
---》transmit_command
----》packet_fragmenter->fragment_and_dispatch(wait_entry->command)
---》transmit_fragment
-》transmit_data
-》write(uart_fd, data + transmitted_length, length); ---uart_fd是打开的串口描述符。
static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
assert(data != NULL);
assert(length > 0);
if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
LOG_ERROR("%s invalid data type: %d", __func__, type);
return 0;
}
// Write the signal byte right before the data
--data;
uint8_t previous_byte = *data;
*(data) = type;
++length;
uint16_t transmitted_length = 0;
while (length > 0) {
ssize_t ret = write(uart_fd, data + transmitted_length, length);
switch (ret) {
case -1:
LOG_ERROR("In %s, error writing to the uart serial port: %s", __func__, strerror(errno));
goto done;
case 0:
// If we wrote nothing, don't loop more because we
// can't go to infinity or beyond
goto done;
default:
transmitted_length += ret;
length -= ret;
break;
}
}
done:;
// Be nice and restore the old value of that byte
*(data) = previous_byte;
// Remove the signal byte from our transmitted length, if it was actually written
if (transmitted_length > 0)
--transmitted_length;
return transmitted_length;
}
--》【hal->read_data】--》
hci_layer.c
static const hci_hal_callbacks_t hal_callbacks = {
hal_says_data_ready
};
hal->init(&hal_callbacks, thread);
hal = hci_hal_get_interface();
这里的串口号,和写操作的uart_fd是一样的,创建的uart_stream是串口的数据的读者对象。
static bool hal_open() {
LOG_INFO("%s", __func__);
// TODO(zachoverflow): close if already open / or don't reopen (maybe at the hci layer level)
int fd_array[CH_MAX];
int number_of_ports = vendor->send_command(VENDOR_OPEN_USERIAL, &fd_array);
if (number_of_ports != 1) {
LOG_ERROR("%s opened the wrong number of ports: got %d, expected 1.", __func__, number_of_ports);
goto error;
}
uart_fd = fd_array[0];
if (uart_fd == INVALID_FD) {
LOG_ERROR("%s unable to open the uart serial port.", __func__);
goto error;
}
uart_stream = eager_reader_new(uart_fd, &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_single_channel");
if (!uart_stream) {
LOG_ERROR("%s unable to create eager reader for the uart serial port.", __func__);
goto error;
}
stream_has_interpretation = false;
stream_corruption_detected = false;
stream_corruption_bytes_to_ignore = 0;
eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
// Raise thread priorities to keep up with audio
thread_set_priority(thread, HCI_THREAD_PRIORITY);
thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
return true;
error:
interface.close();
return false;
}
该读者对象被eager_reader_register注册,并被放在名为“hci_thread”的线程上,并在数据来临时,通过event_uart_has_bytes通知上层数据来了。
该函数的data_ready是在hal层init时上层回调函数hal_says_data_ready,这样将数据向上层传送。
// See what data is waiting, and notify the upper layer
static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
if (stream_has_interpretation) {
callbacks->data_ready(current_data_type);
} else {
uint8_t type_byte;
if (eager_reader_read(reader, &type_byte, 1, true) == 0) {
LOG_ERROR("%s could not read HCI message type", __func__);
return;
}
if (stream_corrupted_during_le_scan_workaround(type_byte))
return;
if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
return;
}
stream_has_interpretation = true;
current_data_type = type_byte;
}
}
这个函数将收到的数据reassamble,并且进一步向上层传输。