蓝牙之十七-bluedroid scan流程
2016-10-16 22:35
519 查看
蓝牙扫描过程是指扫描蓝牙设备
第一张图显示的是安卓设置setting菜单栏中有Bluetooth这一项,点进去以后,点击右上角显示如下的截图。
其中Refresh就是刷新设备列表,也就会扫描设备信息。
上图显示的三个菜单在BluetoothSettings.java文件。
协议栈层
所在目录是/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)
btif/src/bluetooth.c
扫描分为BR/EDR类型的设备和BLE类型的设备。
BR/EDR类型设备扫描参数存在tBTA_DM_INQ结构体里,参数如下:
查询模式(general or limited),
查询的长(以1.28s为单位,最长1.28*10s),
最大的查询响应量(0表示无限制响应)。
查询过滤类型(清除,按设备类型过滤,按设备地址过滤)。
如果是BLE类型的扫描还有如下参数需要设置一些其它的参数,这里以正常设备扫描流程说明过程。
这里将BR/EDR情况的参数设置罗列如下(dm 是device management简称):
上述的p_msg是workqueue中的message。
bta_dm_main.c
BTM_StartInquiry中的第一个参数中inq_params,也就是btif_dm_start_discovery发送的参数。
该函数判断是否支持BLE扫描,如果支持调用btm_ble_start_inquiry进行BLE模式扫描,对于BR/EDR模式,则调用btm_set_inq_event_filter进行扫描。
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是打开的串口描述符。
hci_layer.c
该函数的data_ready是在hal层init时上层回调函数hal_says_data_ready,这样将数据向上层传送。
app层
这里有两张截图第一张图显示的是安卓设置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实现相关功能;
</frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java> 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(); } } }
framework层
首先要求权限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。
package中的BT service调用
</packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java> 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(); } }
JNI层调用
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)
btif/src/bluetooth.c
static int start_discovery(void) { /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_dm_start_discovery(); }
btif/src/btif_dm.c
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_dm_api.c
查找工作不在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);
btu_task.c
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。
bta_sys_main.c
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是函数指针集,
<bta_sys_main.c> 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,状态机管理穿插在整个蓝牙管理中。
bta_dm_main.c
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 };
bta_dm_act.c
这里忽略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发送的参数。
btm_inq.c
这个函数的查询过程包括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进行扫描。
btm_inq.c
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); }这个函数根据条件设置查询的过滤项。
hci和tty通信
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
<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();
hci_hal_h4.c
这里的串口号,和写操作的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,并且进一步向上层传输。
相关文章推荐
- BlueDroid 蓝牙启动流程分析
- 蓝牙之十五-bluedroid enable流程
- Android BlueDroid(二):BlueDroid蓝牙开启过程init
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比) .
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Android BlueDroid(二):BlueDroid蓝牙开启过程init
- Android Bluetooth Stack: Bluedroid(四):Scan remote devices
- 蓝牙系列之BlueDroid与MTK代码分布
- Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比)
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Android BlueDroid(二):BlueDroid蓝牙开启过程init
- Android BlueDroid(二):BlueDroid蓝牙开启过程init
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- [Android M] Bluedroid修改蓝牙默认名称
- Android BlueDroid(二):BlueDroid蓝牙开启过程init
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- 原:android4.2.2蓝牙源码阅读--bluedroid部分
- android bluedroid bt 读写特性值的流程
- 蓝牙系列之BlueDroid与MTK代码分布