Bluetooth inquiryプロセスのコマンド
34476 ワード
Androidの上のBluetooth inquiryはインタフェースを設定し、Bluetoothを開くと周辺のBluetoothデバイスを自動的に検索し、最終的にプロトコルスタックのstart_に呼び出されます.discoveryインタフェース、この文章はインタフェースの呼び出しプロセスとcontrollerとのインタラクションプロセスを分析します.
上のコードの主な仕事は、関連する検索のパラメータを設定し、BTA_を呼び出すことです.DmSearch(&inq_params, services, bte_search_devices_evt); を選択して設定できます.
ここでは改めて送信BTAを整理しますDmSearchのパラメータ:
BTAを見てみましょうDmSearchの具体的な実装
ここで発見したのはmsgを組み立ててbtuスレッド処理に送信し、ここでbtuスレッドに送信するパラメータを整理することです.
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;//service = 0 p_msg->p_cback = p_cback;//bte_search_devices_evt
p_msg->rs_res = BTA_DM_RS_NONE;
検索してみましょうBTA_DM_API_SEARCH_EVTが実行する関数:bta_dm_search_start
上のコードが実行されたらbtaを見てみましょうdm_search_cbの各構造の値:
bta_dm_search_cb.p_search_cback = bte_search_devices_evt
bta_dm_search_cb.services = 0;
bta_dm_search_cb.num_uuid =0;
bta_dm_search_cb.p_srvc_uuid = NULL;
続いてBTM_を見ていきますStartInquiryの実装は、ここで簡単に分析することができます.入力された3つのパラメータ:
最初のパラメータは、上に組み立てたinquiryに関する設定です.
2番目のパラメータはデバイス呼び出しへのスキャンです
3番目のパラメータはスキャン完了時に呼び出されます
上のコードは主に3つのことをしました.いくつかのパラメータをtBTM_に保存するINQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_varsという構造. p_inq->scan_type = INQ_GENERAL; p_inq->inqparms = *p_inqparms; 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 = 0x11(BLE|BREDR)
BLEをするinquiry:btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),p_inqparms->duration) BREDRを作るinquiry:btm_set_inq_event_filter (p_inqparms->filter_cond_type,&p_inqparms->filter_cond)
btm_ble_start_inquiry
上のコードの論理は非常に簡単で、注意しなければならないのはp_です.inq->inq_Active|=modeとp_ble_cb->scan_activity |= mode;
Bleのスキャンが開始され、持続時間は10 s=10*1000 msで、タイマがタイムアウトした後にscanがキャンセルされます.
上からinquiryから送信されたble scanの優先度はまだ高く、現在のscanの動作を停止することもわかります.この時点でバックグラウンドにobserve動作がある場合は、停止されます.
btm_set_inq_event_filter
主にHCIを送信していますFILTER_INQUIRY_RESULT、およびステータスビットが設定されている:btm_cb.btm_inq_vars.inqfilt_active = TRUE
検索の動作は、この関数の完了イベントで行われるに違いありません.
上のコードの主なことは:
p_inq->state = BTM_INQ_ACTIVE_STATE; p_inq->inqfilt_active = FALSE; btm_initiate_inquiry (p_inq);
続けてbtm_initiate_inquiryの実装:
上のコードではbtsnd_に重点を置いていますhcic_inquiry(*lap, p_inqparms->duration, 0)
その実現はcontrollerにinquiryのコマンドを送信することである.ここで、durationパラメータは10であり、対応する実際の値は10*1.28 sであり、12.8秒後にinquiry completeイベントが送信される.
inquiryのコマンド送信プロセスはここまで分析される.
転載先:https://www.cnblogs.com/libs-liu/p/9229253.html
static int start_discovery(void)
{
/* sanity check */
if (interface_ready() == FALSE)
return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
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;
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS));
/* Cleanup anything remaining on index 0 */
BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_DELETE, 0, &adv_filt_param, NULL,
bte_scan_filt_param_cfg_evt, 0);
/* Add an allow-all filter on index 0*/
adv_filt_param.dely_mode = IMMEDIATE_DELY_MODE;
adv_filt_param.feat_seln = ALLOW_ALL_FILTER;
adv_filt_param.filt_logic_type = BTA_DM_BLE_PF_FILT_LOGIC_OR;
adv_filt_param.list_logic_type = BTA_DM_BLE_PF_LIST_LOGIC_OR;
adv_filt_param.rssi_low_thres = LOWEST_RSSI_VALUE;
adv_filt_param.rssi_high_thres = LOWEST_RSSI_VALUE;
BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_ADD, 0, &adv_filt_param, NULL,
bte_scan_filt_param_cfg_evt, 0);
/* TODO: Do we need to handle multiple inquiries at the same time? */
/* Set inquiry params and call API */
inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_GENERAL_INQUIRY;// inquiry ,ble bredr
#else
inq_params.mode = BTA_DM_GENERAL_INQUIRY;
#endif
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;//
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;// response
inq_params.report_dup = TRUE;
inq_params.filter_type = BTA_DM_INQ_CLR;//0
/* 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_を呼び出すことです.DmSearch(&inq_params, services, bte_search_devices_evt); を選択して設定できます.
ここでは改めて送信BTAを整理しますDmSearchのパラメータ:
inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_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;//0
tBTA_SERVICE_MASK services = 0;
bte_search_devices_evt , btif_dm.c,
bta_dm_search_cb.p_search_cback = bte_search_devices_evt
BTAを見てみましょうDmSearchの具体的な実装
/*******************************************************************************
**
** Function BTA_DmSearch
**
** Description This function searches for peer Bluetooth devices. It performs
** an inquiry and gets the remote name for devices. Service
** discovery is done if services is non zero
**
**
** Returns void
**
*******************************************************************************/
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を組み立ててbtuスレッド処理に送信し、ここでbtuスレッドに送信するパラメータを整理することです.
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;//service = 0 p_msg->p_cback = p_cback;//bte_search_devices_evt
p_msg->rs_res = BTA_DM_RS_NONE;
検索してみましょうBTA_DM_API_SEARCH_EVTが実行する関数:bta_dm_search_start
/*******************************************************************************
**
** Function bta_dm_search_start
**
** Description Starts an inquiry
**
**
** Returns void
**
*******************************************************************************/
void bta_dm_search_start (tBTA_DM_MSG *p_data)
{
tBTM_INQUIRY_CMPL result;
#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->search.num_uuid);
bta_dm_gattc_register();
#endif
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);
/* save search params */
bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
bta_dm_search_cb.services = p_data->search.services;
#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
p_data->search.p_uuid != NULL)// uuid, copy bta_dm_search_cb.p_srvc_uuid
{
bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)
memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
}
#endif
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);//
if (result.status != BTM_CMD_STARTED)
{
result.num_resp = 0;
bta_dm_inq_cmpl_cb ((void *)&result);// ,
}
}
上のコードが実行されたらbtaを見てみましょうdm_search_cbの各構造の値:
bta_dm_search_cb.p_search_cback = bte_search_devices_evt
bta_dm_search_cb.services = 0;
bta_dm_search_cb.num_uuid =0;
bta_dm_search_cb.p_srvc_uuid = NULL;
続いてBTM_を見ていきますStartInquiryの実装は、ここで簡単に分析することができます.入力された3つのパラメータ:
最初のパラメータは、上に組み立てたinquiryに関する設定です.
2番目のパラメータはデバイス呼び出しへのスキャンです
3番目のパラメータはスキャン完了時に呼び出されます
/*******************************************************************************
**
** Function BTM_StartInquiry
**
** Description This function is called to start an inquiry.
**
** Parameters: p_inqparms - pointer to the inquiry information
** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
** max_resps - maximum amount of devices to search for before ending the inquiry
** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
** BTM_FILTER_COND_BD_ADDR
** filter_cond - value for the filter (based on filter_cond_type)
**
** p_results_cb - Pointer to the callback routine which gets called
** upon receipt of an inquiry result. If this field is
** NULL, the application is not notified.
**
** p_cmpl_cb - Pointer to the callback routine which gets called
** upon completion. If this field is NULL, the
** application is not notified when completed.
** Returns tBTM_STATUS
** BTM_CMD_STARTED if successfully initiated
** BTM_BUSY if already in progress
** BTM_ILLEGAL_VALUE if parameter(s) are out of range
** BTM_NO_RESOURCES if could not allocate resources to start the command
** BTM_WRONG_MODE if the device is not up.
**
*******************************************************************************/
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;
p_inq->scan_type = INQ_GENERAL;
...
/* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;// inquiry
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;//active
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;//0x11
/* start LE inquiry here if requested */
if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK))
{
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;// inquiry ,mode 0
#endif
}
/* BR/EDR inquiry portion */
...
/* 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)// BRRDR , , , bredr inquiry
p_inq->state = BTM_INQ_INACTIVE_STATE;
return (status);
}
上のコードは主に3つのことをしました.
btm_ble_start_inquiry
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
{
tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
...
if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))// scan , scan
{
btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,//active scan
BTM_BLE_LOW_LATENCY_SCAN_INT,
BTM_BLE_LOW_LATENCY_SCAN_WIN,
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
SP_ADV_ALL);
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* enable IRK list */
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
p_ble_cb->inq_var.scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
status = btm_ble_start_scan();// scan
}
else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) ||
(p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) {// scan , scan, scan
btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI,
BTM_BLE_LOW_LATENCY_SCAN_INT,
BTM_BLE_LOW_LATENCY_SCAN_WIN,
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
SP_ADV_ALL);
btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
}
if (status == BTM_CMD_STARTED)
{
p_inq->inq_active |= mode;//
p_ble_cb->scan_activity |= mode;
if (duration != 0)
{
/* start inquiry timer */
btu_start_timer (&p_inq->inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration);// , disable scan
}
}
return status;
}
上のコードの論理は非常に簡単で、注意しなければならないのはp_です.inq->inq_Active|=modeとp_ble_cb->scan_activity |= mode;
Bleのスキャンが開始され、持続時間は10 s=10*1000 msで、タイマがタイムアウトした後にscanがキャンセルされます.
上からinquiryから送信されたble scanの優先度はまだ高く、現在のscanの動作を停止することもわかります.この時点でバックグラウンドにobserve動作がある場合は、停止されます.
btm_set_inq_event_filter
static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
tBTM_INQ_FILT_COND *p_filt_cond)
{
...
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を送信していますFILTER_INQUIRY_RESULT、およびステータスビットが設定されている:btm_cb.btm_inq_vars.inqfilt_active = TRUE
検索の動作は、この関数の完了イベントで行われるに違いありません.
static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_len,
void *p_cplt_cback)
{
switch (opcode)
{
case HCI_INQUIRY_CANCEL:
/* Tell inquiry processing that we are done */
btm_process_cancel_complete(HCI_SUCCESS, BTM_BR_INQUIRY_MASK);
break;
case HCI_SET_EVENT_FILTER:
btm_event_filter_complete (p);//
break;
void btm_event_filter_complete (UINT8 *p)
{
UINT8 hci_status;
tBTM_STATUS status;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
tBTM_CMPL_CB *p_cb = p_inq->p_inqfilter_cmpl_cb;
...
/* Only process the inquiry filter; Ignore the connection filter until it
is used by the upper layers */
if (p_inq->inqfilt_active == TRUE ) //
{
/* Extract the returned status from the buffer */
STREAM_TO_UINT8 (hci_status, p);
if (hci_status != HCI_SUCCESS)
{
/* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)", hci_status);
status = BTM_ERR_PROCESSING;
}
else
status = BTM_SUCCESS;
/* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
callback function to notify the initiator that it has completed */
if (p_inq->state == BTM_INQ_INACTIVE_STATE)// active
{
p_inq->inqfilt_active = FALSE;
if (p_cb)
(*p_cb) (&status);
}
else /* An inquiry is active (the set filter command was internally generated),
process the next state of the process (Set a new filter or start the inquiry). */
{
if(status != BTM_SUCCESS)
{
/* Process the inquiry complete (Error Status) */
btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
/* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
p_inq->inqfilt_active = FALSE;
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
p_inq->state = BTM_INQ_INACTIVE_STATE;
return;
}
/* Check to see if a new filter needs to be set up */
if (p_inq->state == BTM_INQ_CLR_FILT_STATE)
{
if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED)
{
p_inq->state = BTM_INQ_SET_FILT_STATE;
}
else /* Error setting the filter: Call the initiator's callback function to indicate a failure */
{
p_inq->inqfilt_active = FALSE;
/* Process the inquiry complete (Error Status) */
btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
}
}
else /* Initiate the Inquiry or Periodic Inquiry */
{
p_inq->state = BTM_INQ_ACTIVE_STATE;//
p_inq->inqfilt_active = FALSE;// false
btm_initiate_inquiry (p_inq);//
}
}
}
}
上のコードの主なことは:
p_inq->state = BTM_INQ_ACTIVE_STATE; p_inq->inqfilt_active = FALSE; btm_initiate_inquiry (p_inq);
続けてbtm_initiate_inquiryの実装:
static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
{
const LAP *lap;
tBTM_INQ_PARMS *p_inqparms = &p_inq->inqparms;
btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
...
lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;// LAP
{
btm_clr_inq_result_flt();//
/* Allocate memory to hold bd_addrs responding */
if ((p_inq->p_bd_db = (tINQ_BDADDR *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
{
p_inq->max_bd_entries = (UINT16)(GKI_MAX_BUF_SIZE / sizeof(tINQ_BDADDR));
memset(p_inq->p_bd_db, 0, GKI_MAX_BUF_SIZE);
/* BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
p_inq->max_bd_entries); */
}
if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0))// inquiry
btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
}
}
上のコードではbtsnd_に重点を置いていますhcic_inquiry(*lap, p_inqparms->duration, 0)
その実現はcontrollerにinquiryのコマンドを送信することである.ここで、durationパラメータは10であり、対応する実際の値は10*1.28 sであり、12.8秒後にinquiry completeイベントが送信される.
inquiryのコマンド送信プロセスはここまで分析される.
転載先:https://www.cnblogs.com/libs-liu/p/9229253.html