1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2014 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  This file contains functions that handle inquiries. These include
22 *  setting discoverable mode, controlling the mode of the Baseband, and
23 *  maintaining a small database of inquiry responses, with API for people
24 *  to browse it.
25 *
26 ******************************************************************************/
27
28#include <stddef.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "device/include/controller.h"
34#include "osi/include/osi.h"
35#include "osi/include/time.h"
36
37#include "advertise_data_parser.h"
38#include "bt_common.h"
39#include "bt_types.h"
40#include "btm_api.h"
41#include "btm_int.h"
42#include "btu.h"
43#include "hcidefs.h"
44#include "hcimsgs.h"
45
46/* 3 second timeout waiting for responses */
47#define BTM_INQ_REPLY_TIMEOUT_MS (3 * 1000)
48
49/* TRUE to enable DEBUG traces for btm_inq */
50#ifndef BTM_INQ_DEBUG
51#define BTM_INQ_DEBUG FALSE
52#endif
53
54extern fixed_queue_t* btu_general_alarm_queue;
55
56/******************************************************************************/
57/*               L O C A L    D A T A    D E F I N I T I O N S                */
58/******************************************************************************/
59static const LAP general_inq_lap = {0x9e, 0x8b, 0x33};
60static const LAP limited_inq_lap = {0x9e, 0x8b, 0x00};
61
62const uint16_t BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES] = {
63    UUID_SERVCLASS_SERVICE_DISCOVERY_SERVER,
64    /*    UUID_SERVCLASS_BROWSE_GROUP_DESCRIPTOR,   */
65    /*    UUID_SERVCLASS_PUBLIC_BROWSE_GROUP,       */
66    UUID_SERVCLASS_SERIAL_PORT, UUID_SERVCLASS_LAN_ACCESS_USING_PPP,
67    UUID_SERVCLASS_DIALUP_NETWORKING, UUID_SERVCLASS_IRMC_SYNC,
68    UUID_SERVCLASS_OBEX_OBJECT_PUSH, UUID_SERVCLASS_OBEX_FILE_TRANSFER,
69    UUID_SERVCLASS_IRMC_SYNC_COMMAND, UUID_SERVCLASS_HEADSET,
70    UUID_SERVCLASS_CORDLESS_TELEPHONY, UUID_SERVCLASS_AUDIO_SOURCE,
71    UUID_SERVCLASS_AUDIO_SINK, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
72    /*    UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION,    */
73    UUID_SERVCLASS_AV_REMOTE_CONTROL,
74    /*    UUID_SERVCLASS_VIDEO_CONFERENCING,        */
75    UUID_SERVCLASS_INTERCOM, UUID_SERVCLASS_FAX,
76    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
77    /*    UUID_SERVCLASS_WAP,                       */
78    /*    UUID_SERVCLASS_WAP_CLIENT,                */
79    UUID_SERVCLASS_PANU, UUID_SERVCLASS_NAP, UUID_SERVCLASS_GN,
80    UUID_SERVCLASS_DIRECT_PRINTING,
81    /*    UUID_SERVCLASS_REFERENCE_PRINTING,        */
82    UUID_SERVCLASS_IMAGING, UUID_SERVCLASS_IMAGING_RESPONDER,
83    UUID_SERVCLASS_IMAGING_AUTO_ARCHIVE, UUID_SERVCLASS_IMAGING_REF_OBJECTS,
84    UUID_SERVCLASS_HF_HANDSFREE, UUID_SERVCLASS_AG_HANDSFREE,
85    UUID_SERVCLASS_DIR_PRT_REF_OBJ_SERVICE,
86    /*    UUID_SERVCLASS_REFLECTED_UI,              */
87    UUID_SERVCLASS_BASIC_PRINTING, UUID_SERVCLASS_PRINTING_STATUS,
88    UUID_SERVCLASS_HUMAN_INTERFACE, UUID_SERVCLASS_CABLE_REPLACEMENT,
89    UUID_SERVCLASS_HCRP_PRINT, UUID_SERVCLASS_HCRP_SCAN,
90    /*    UUID_SERVCLASS_COMMON_ISDN_ACCESS,        */
91    /*    UUID_SERVCLASS_VIDEO_CONFERENCING_GW,     */
92    /*    UUID_SERVCLASS_UDI_MT,                    */
93    /*    UUID_SERVCLASS_UDI_TA,                    */
94    /*    UUID_SERVCLASS_VCP,                       */
95    UUID_SERVCLASS_SAP, UUID_SERVCLASS_PBAP_PCE, UUID_SERVCLASS_PBAP_PSE,
96    UUID_SERVCLASS_PHONE_ACCESS, UUID_SERVCLASS_HEADSET_HS,
97    UUID_SERVCLASS_PNP_INFORMATION,
98    /*    UUID_SERVCLASS_GENERIC_NETWORKING,        */
99    /*    UUID_SERVCLASS_GENERIC_FILETRANSFER,      */
100    /*    UUID_SERVCLASS_GENERIC_AUDIO,             */
101    /*    UUID_SERVCLASS_GENERIC_TELEPHONY,         */
102    /*    UUID_SERVCLASS_UPNP_SERVICE,              */
103    /*    UUID_SERVCLASS_UPNP_IP_SERVICE,           */
104    /*    UUID_SERVCLASS_ESDP_UPNP_IP_PAN,          */
105    /*    UUID_SERVCLASS_ESDP_UPNP_IP_LAP,          */
106    /*    UUID_SERVCLASS_ESDP_UPNP_IP_L2CAP,        */
107    UUID_SERVCLASS_VIDEO_SOURCE, UUID_SERVCLASS_VIDEO_SINK,
108    /*    UUID_SERVCLASS_VIDEO_DISTRIBUTION         */
109    UUID_SERVCLASS_MESSAGE_ACCESS, UUID_SERVCLASS_MESSAGE_NOTIFICATION,
110    UUID_SERVCLASS_HDP_SOURCE, UUID_SERVCLASS_HDP_SINK};
111
112/******************************************************************************/
113/*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
114/******************************************************************************/
115static void btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST* p_inq);
116static tBTM_STATUS btm_set_inq_event_filter(uint8_t filter_cond_type,
117                                            tBTM_INQ_FILT_COND* p_filt_cond);
118static void btm_clr_inq_result_flt(void);
119
120static uint8_t btm_convert_uuid_to_eir_service(uint16_t uuid16);
121static void btm_set_eir_uuid(uint8_t* p_eir, tBTM_INQ_RESULTS* p_results);
122static const uint8_t* btm_eir_get_uuid_list(uint8_t* p_eir, size_t eir_len,
123                                            uint8_t uuid_size,
124                                            uint8_t* p_num_uuid,
125                                            uint8_t* p_uuid_list_type);
126static uint16_t btm_convert_uuid_to_uuid16(const uint8_t* p_uuid,
127                                           uint8_t uuid_size);
128
129/*******************************************************************************
130 *
131 * Function         BTM_SetDiscoverability
132 *
133 * Description      This function is called to set the device into or out of
134 *                  discoverable mode. Discoverable mode means inquiry
135 *                  scans are enabled.  If a value of '0' is entered for window
136 *                  or interval, the default values are used.
137 *
138 * Returns          BTM_SUCCESS if successful
139 *                  BTM_BUSY if a setting of the filter is already in progress
140 *                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
141 *                  BTM_ILLEGAL_VALUE if a bad parameter was detected
142 *                  BTM_WRONG_MODE if the device is not up.
143 *
144 ******************************************************************************/
145tBTM_STATUS BTM_SetDiscoverability(uint16_t inq_mode, uint16_t window,
146                                   uint16_t interval) {
147  uint8_t scan_mode = 0;
148  uint16_t service_class;
149  uint8_t* p_cod;
150  uint8_t major, minor;
151  DEV_CLASS cod;
152  LAP temp_lap[2];
153  bool is_limited;
154  bool cod_limited;
155
156  BTM_TRACE_API("BTM_SetDiscoverability");
157  if (controller_get_interface()->supports_ble()) {
158    if (btm_ble_set_discoverability((uint16_t)(inq_mode)) == BTM_SUCCESS) {
159      btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
160      btm_cb.btm_inq_vars.discoverable_mode |=
161          (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
162    }
163  }
164  inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
165
166  /*** Check mode parameter ***/
167  if (inq_mode > BTM_MAX_DISCOVERABLE) return (BTM_ILLEGAL_VALUE);
168
169  /* Make sure the controller is active */
170  if (!controller_get_interface()->get_is_ready()) return (BTM_DEV_RESET);
171
172  /* If the window and/or interval is '0', set to default values */
173  if (!window) window = BTM_DEFAULT_DISC_WINDOW;
174
175  if (!interval) interval = BTM_DEFAULT_DISC_INTERVAL;
176
177  BTM_TRACE_API(
178      "BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window "
179      "0x%04x, interval 0x%04x",
180      inq_mode, window, interval);
181
182  /*** Check for valid window and interval parameters ***/
183  /*** Only check window and duration if mode is connectable ***/
184  if (inq_mode != BTM_NON_DISCOVERABLE) {
185    /* window must be less than or equal to interval */
186    if (window < HCI_MIN_INQUIRYSCAN_WINDOW ||
187        window > HCI_MAX_INQUIRYSCAN_WINDOW ||
188        interval < HCI_MIN_INQUIRYSCAN_INTERVAL ||
189        interval > HCI_MAX_INQUIRYSCAN_INTERVAL || window > interval) {
190      return (BTM_ILLEGAL_VALUE);
191    }
192  }
193
194  /* Set the IAC if needed */
195  if (inq_mode != BTM_NON_DISCOVERABLE) {
196    if (inq_mode & BTM_LIMITED_DISCOVERABLE) {
197      /* Use the GIAC and LIAC codes for limited discoverable mode */
198      memcpy(temp_lap[0], limited_inq_lap, LAP_LEN);
199      memcpy(temp_lap[1], general_inq_lap, LAP_LEN);
200
201      btsnd_hcic_write_cur_iac_lap(2, (LAP * const)temp_lap);
202    } else {
203      btsnd_hcic_write_cur_iac_lap(1, (LAP * const) & general_inq_lap);
204    }
205
206    scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
207  }
208
209  /* Send down the inquiry scan window and period if changed */
210  if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
211      (interval != btm_cb.btm_inq_vars.inq_scan_period)) {
212    btsnd_hcic_write_inqscan_cfg(interval, window);
213    btm_cb.btm_inq_vars.inq_scan_window = window;
214    btm_cb.btm_inq_vars.inq_scan_period = interval;
215  }
216
217  if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK)
218    scan_mode |= HCI_PAGE_SCAN_ENABLED;
219
220  btsnd_hcic_write_scan_enable(scan_mode);
221  btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
222  btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
223
224  /* Change the service class bit if mode has changed */
225  p_cod = BTM_ReadDeviceClass();
226  BTM_COD_SERVICE_CLASS(service_class, p_cod);
227  is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? true : false;
228  cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false;
229  if (is_limited ^ cod_limited) {
230    BTM_COD_MINOR_CLASS(minor, p_cod);
231    BTM_COD_MAJOR_CLASS(major, p_cod);
232    if (is_limited)
233      service_class |= BTM_COD_SERVICE_LMTD_DISCOVER;
234    else
235      service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER;
236
237    FIELDS_TO_COD(cod, minor, major, service_class);
238    (void)BTM_SetDeviceClass(cod);
239  }
240
241  return (BTM_SUCCESS);
242}
243
244/*******************************************************************************
245 *
246 * Function         BTM_SetInquiryScanType
247 *
248 * Description      This function is called to set the iquiry scan-type to
249 *                  standard or interlaced.
250 *
251 * Returns          BTM_SUCCESS if successful
252 *                  BTM_MODE_UNSUPPORTED if not a 1.2 device
253 *                  BTM_WRONG_MODE if the device is not up.
254 *
255 ******************************************************************************/
256tBTM_STATUS BTM_SetInquiryScanType(uint16_t scan_type) {
257  BTM_TRACE_API("BTM_SetInquiryScanType");
258  if (scan_type != BTM_SCAN_TYPE_STANDARD &&
259      scan_type != BTM_SCAN_TYPE_INTERLACED)
260    return (BTM_ILLEGAL_VALUE);
261
262  /* whatever app wants if device is not 1.2 scan type should be STANDARD */
263  if (!controller_get_interface()->supports_interlaced_inquiry_scan())
264    return (BTM_MODE_UNSUPPORTED);
265
266  /* Check for scan type if configuration has been changed */
267  if (scan_type != btm_cb.btm_inq_vars.inq_scan_type) {
268    if (BTM_IsDeviceUp()) {
269      btsnd_hcic_write_inqscan_type((uint8_t)scan_type);
270      btm_cb.btm_inq_vars.inq_scan_type = scan_type;
271    } else
272      return (BTM_WRONG_MODE);
273  }
274  return (BTM_SUCCESS);
275}
276
277/*******************************************************************************
278 *
279 * Function         BTM_SetPageScanType
280 *
281 * Description      This function is called to set the page scan-type to
282 *                  standard or interlaced.
283 *
284 * Returns          BTM_SUCCESS if successful
285 *                  BTM_MODE_UNSUPPORTED if not a 1.2 device
286 *                  BTM_WRONG_MODE if the device is not up.
287 *
288 ******************************************************************************/
289tBTM_STATUS BTM_SetPageScanType(uint16_t scan_type) {
290  BTM_TRACE_API("BTM_SetPageScanType");
291  if (scan_type != BTM_SCAN_TYPE_STANDARD &&
292      scan_type != BTM_SCAN_TYPE_INTERLACED)
293    return (BTM_ILLEGAL_VALUE);
294
295  /* whatever app wants if device is not 1.2 scan type should be STANDARD */
296  if (!controller_get_interface()->supports_interlaced_inquiry_scan())
297    return (BTM_MODE_UNSUPPORTED);
298
299  /* Check for scan type if configuration has been changed */
300  if (scan_type != btm_cb.btm_inq_vars.page_scan_type) {
301    if (BTM_IsDeviceUp()) {
302      btsnd_hcic_write_pagescan_type((uint8_t)scan_type);
303      btm_cb.btm_inq_vars.page_scan_type = scan_type;
304    } else
305      return (BTM_WRONG_MODE);
306  }
307  return (BTM_SUCCESS);
308}
309
310/*******************************************************************************
311 *
312 * Function         BTM_SetInquiryMode
313 *
314 * Description      This function is called to set standard or with RSSI
315 *                  mode of the inquiry for local device.
316 *
317 * Output Params:   mode - standard, with RSSI, extended
318 *
319 * Returns          BTM_SUCCESS if successful
320 *                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
321 *                  BTM_ILLEGAL_VALUE if a bad parameter was detected
322 *                  BTM_WRONG_MODE if the device is not up.
323 *
324 ******************************************************************************/
325tBTM_STATUS BTM_SetInquiryMode(uint8_t mode) {
326  const controller_t* controller = controller_get_interface();
327  BTM_TRACE_API("BTM_SetInquiryMode");
328  if (mode == BTM_INQ_RESULT_STANDARD) {
329    /* mandatory mode */
330  } else if (mode == BTM_INQ_RESULT_WITH_RSSI) {
331    if (!controller->supports_rssi_with_inquiry_results())
332      return (BTM_MODE_UNSUPPORTED);
333  } else if (mode == BTM_INQ_RESULT_EXTENDED) {
334    if (!controller->supports_extended_inquiry_response())
335      return (BTM_MODE_UNSUPPORTED);
336  } else
337    return (BTM_ILLEGAL_VALUE);
338
339  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
340
341  btsnd_hcic_write_inquiry_mode(mode);
342
343  return (BTM_SUCCESS);
344}
345
346/*******************************************************************************
347 *
348 * Function         BTM_ReadDiscoverability
349 *
350 * Description      This function is called to read the current discoverability
351 *                  mode of the device.
352 *
353 * Output Params:   p_window - current inquiry scan duration
354 *                  p_interval - current inquiry scan interval
355 *
356 * Returns          BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
357 *                  BTM_GENERAL_DISCOVERABLE
358 *
359 ******************************************************************************/
360uint16_t BTM_ReadDiscoverability(uint16_t* p_window, uint16_t* p_interval) {
361  BTM_TRACE_API("BTM_ReadDiscoverability");
362  if (p_window) *p_window = btm_cb.btm_inq_vars.inq_scan_window;
363
364  if (p_interval) *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
365
366  return (btm_cb.btm_inq_vars.discoverable_mode);
367}
368
369/*******************************************************************************
370 *
371 * Function         BTM_SetPeriodicInquiryMode
372 *
373 * Description      This function is called to set the device periodic inquiry
374 *                  mode. If the duration is zero, the periodic inquiry mode is
375 *                  cancelled.
376 *
377 *                  Note: We currently do not allow concurrent inquiry and
378 *                  periodic inquiry.
379 *
380 * Parameters:      p_inqparms - pointer to the inquiry information
381 *                      mode - GENERAL or LIMITED inquiry
382 *                      duration - length in 1.28 sec intervals (If '0', the
383 *                                 inquiry is CANCELLED)
384 *                      max_resps - maximum amount of devices to search for
385 *                                  before ending the inquiry
386 *                      filter_cond_type - BTM_CLR_INQUIRY_FILTER,
387 *                                         BTM_FILTER_COND_DEVICE_CLASS, or
388 *                                         BTM_FILTER_COND_BD_ADDR
389 *                      filter_cond - value for the filter (based on
390 *                                                          filter_cond_type)
391 *
392 *                  max_delay - maximum amount of time between successive
393 *                              inquiries
394 *                  min_delay - minimum amount of time between successive
395 *                              inquiries
396 *                  p_results_cb - callback returning pointer to results
397 *                              (tBTM_INQ_RESULTS)
398 *
399 * Returns          BTM_CMD_STARTED if successfully started
400 *                  BTM_ILLEGAL_VALUE if a bad parameter is detected
401 *                  BTM_NO_RESOURCES if could not allocate a message buffer
402 *                  BTM_SUCCESS - if cancelling the periodic inquiry
403 *                  BTM_BUSY - if an inquiry is already active
404 *                  BTM_WRONG_MODE if the device is not up.
405 *
406 ******************************************************************************/
407tBTM_STATUS BTM_SetPeriodicInquiryMode(tBTM_INQ_PARMS* p_inqparms,
408                                       uint16_t max_delay, uint16_t min_delay,
409                                       tBTM_INQ_RESULTS_CB* p_results_cb) {
410  tBTM_STATUS status;
411  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
412
413  BTM_TRACE_API(
414      "BTM_SetPeriodicInquiryMode: mode: %d, dur: %d, rsps: %d, flt: %d, min: "
415      "%d, max: %d",
416      p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
417      p_inqparms->filter_cond_type, min_delay, max_delay);
418
419  /*** Make sure the device is ready ***/
420  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
421
422  /* Only one active inquiry is allowed in this implementation.
423     Also do not allow an inquiry if the inquiry filter is being updated */
424  if (p_inq->inq_active || p_inq->inqfilt_active) return (BTM_BUSY);
425
426  /* If illegal parameters return false */
427  if (p_inqparms->mode != BTM_GENERAL_INQUIRY &&
428      p_inqparms->mode != BTM_LIMITED_INQUIRY)
429    return (BTM_ILLEGAL_VALUE);
430
431  /* Verify the parameters for this command */
432  if (p_inqparms->duration < BTM_MIN_INQUIRY_LEN ||
433      p_inqparms->duration > BTM_MAX_INQUIRY_LENGTH ||
434      min_delay <= p_inqparms->duration ||
435      min_delay < BTM_PER_INQ_MIN_MIN_PERIOD ||
436      min_delay > BTM_PER_INQ_MAX_MIN_PERIOD || max_delay <= min_delay ||
437      max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
438  /*       max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
439  /*  BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in
440     false always*/
441  {
442    return (BTM_ILLEGAL_VALUE);
443  }
444
445  /* Save the inquiry parameters to be used upon the completion of
446   * setting/clearing the inquiry filter */
447  p_inq->inqparms = *p_inqparms;
448  p_inq->per_min_delay = min_delay;
449  p_inq->per_max_delay = max_delay;
450  p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
451  p_inq->p_inq_results_cb = p_results_cb;
452
453  p_inq->inq_active = (uint8_t)(
454      (p_inqparms->mode == BTM_LIMITED_INQUIRY)
455          ? (BTM_LIMITED_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE)
456          : (BTM_GENERAL_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE));
457
458  /* If a filter is specified, then save it for later and clear the current
459     filter.
460     The setting of the filter is done upon completion of clearing of the
461     previous
462     filter.
463  */
464  if (p_inqparms->filter_cond_type != BTM_CLR_INQUIRY_FILTER) {
465    p_inq->state = BTM_INQ_CLR_FILT_STATE;
466    p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
467  } else /* The filter is not being used so simply clear it; the inquiry can
468            start after this operation */
469    p_inq->state = BTM_INQ_SET_FILT_STATE;
470
471  /* Before beginning the inquiry the current filter must be cleared, so
472   * initiate the command */
473  status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
474                                    &p_inqparms->filter_cond);
475  if (status != BTM_CMD_STARTED) {
476    /* If set filter command is not succesful reset the state */
477    p_inq->p_inq_results_cb = NULL;
478    p_inq->state = BTM_INQ_INACTIVE_STATE;
479  }
480
481  return (status);
482}
483
484/*******************************************************************************
485 *
486 * Function         BTM_CancelPeriodicInquiry
487 *
488 * Description      This function cancels a periodic inquiry
489 *
490 * Returns
491 *                  BTM_NO_RESOURCES if could not allocate a message buffer
492 *                  BTM_SUCCESS - if cancelling the periodic inquiry
493 *                  BTM_WRONG_MODE if the device is not up.
494 *
495 ******************************************************************************/
496tBTM_STATUS BTM_CancelPeriodicInquiry(void) {
497  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
498  tBTM_STATUS status = BTM_SUCCESS;
499  BTM_TRACE_API("BTM_CancelPeriodicInquiry called");
500
501  /*** Make sure the device is ready ***/
502  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
503
504  /* Only cancel if one is active */
505  if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
506    btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
507    btm_cb.btm_inq_vars.p_inq_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
508
509    btsnd_hcic_exit_per_inq();
510
511    /* If the event filter is in progress, mark it so that the processing of the
512       return
513       event will be ignored */
514    if (p_inq->inqfilt_active) p_inq->pending_filt_complete_event++;
515
516    p_inq->inqfilt_active = false;
517    p_inq->inq_counter++;
518  }
519
520  return (status);
521}
522
523/*******************************************************************************
524 *
525 * Function         BTM_SetConnectability
526 *
527 * Description      This function is called to set the device into or out of
528 *                  connectable mode. Discoverable mode means page scans are
529 *                  enabled.
530 *
531 * Returns          BTM_SUCCESS if successful
532 *                  BTM_ILLEGAL_VALUE if a bad parameter is detected
533 *                  BTM_NO_RESOURCES if could not allocate a message buffer
534 *                  BTM_WRONG_MODE if the device is not up.
535 *
536 ******************************************************************************/
537tBTM_STATUS BTM_SetConnectability(uint16_t page_mode, uint16_t window,
538                                  uint16_t interval) {
539  uint8_t scan_mode = 0;
540  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
541
542  BTM_TRACE_API("BTM_SetConnectability");
543
544  if (controller_get_interface()->supports_ble()) {
545    if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS) {
546      return BTM_NO_RESOURCES;
547    }
548    p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
549    p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
550  }
551  page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
552
553  /*** Check mode parameter ***/
554  if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE)
555    return (BTM_ILLEGAL_VALUE);
556
557  /* Make sure the controller is active */
558  if (!controller_get_interface()->get_is_ready()) return (BTM_DEV_RESET);
559
560  /* If the window and/or interval is '0', set to default values */
561  if (!window) window = BTM_DEFAULT_CONN_WINDOW;
562
563  if (!interval) interval = BTM_DEFAULT_CONN_INTERVAL;
564
565  BTM_TRACE_API(
566      "BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, "
567      "interval 0x%04x",
568      page_mode, window, interval);
569
570  /*** Check for valid window and interval parameters ***/
571  /*** Only check window and duration if mode is connectable ***/
572  if (page_mode == BTM_CONNECTABLE) {
573    /* window must be less than or equal to interval */
574    if (window < HCI_MIN_PAGESCAN_WINDOW || window > HCI_MAX_PAGESCAN_WINDOW ||
575        interval < HCI_MIN_PAGESCAN_INTERVAL ||
576        interval > HCI_MAX_PAGESCAN_INTERVAL || window > interval) {
577      return (BTM_ILLEGAL_VALUE);
578    }
579
580    scan_mode |= HCI_PAGE_SCAN_ENABLED;
581  }
582
583  if ((window != p_inq->page_scan_window) ||
584      (interval != p_inq->page_scan_period)) {
585    p_inq->page_scan_window = window;
586    p_inq->page_scan_period = interval;
587    btsnd_hcic_write_pagescan_cfg(interval, window);
588  }
589
590  /* Keep the inquiry scan as previouosly set */
591  if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK)
592    scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
593
594  btsnd_hcic_write_scan_enable(scan_mode);
595  p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
596  p_inq->connectable_mode |= page_mode;
597  return (BTM_SUCCESS);
598}
599
600/*******************************************************************************
601 *
602 * Function         BTM_ReadConnectability
603 *
604 * Description      This function is called to read the current discoverability
605 *                  mode of the device.
606 * Output Params    p_window - current page scan duration
607 *                  p_interval - current time between page scans
608 *
609 * Returns          BTM_NON_CONNECTABLE or BTM_CONNECTABLE
610 *
611 ******************************************************************************/
612uint16_t BTM_ReadConnectability(uint16_t* p_window, uint16_t* p_interval) {
613  BTM_TRACE_API("BTM_ReadConnectability");
614  if (p_window) *p_window = btm_cb.btm_inq_vars.page_scan_window;
615
616  if (p_interval) *p_interval = btm_cb.btm_inq_vars.page_scan_period;
617
618  return (btm_cb.btm_inq_vars.connectable_mode);
619}
620
621/*******************************************************************************
622 *
623 * Function         BTM_IsInquiryActive
624 *
625 * Description      This function returns a bit mask of the current inquiry
626 *                  state
627 *
628 * Returns          BTM_INQUIRY_INACTIVE if inactive (0)
629 *                  BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active
630 *                  BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active
631 *                  BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active
632 *
633 ******************************************************************************/
634uint16_t BTM_IsInquiryActive(void) {
635  BTM_TRACE_API("BTM_IsInquiryActive");
636
637  return (btm_cb.btm_inq_vars.inq_active);
638}
639
640/*******************************************************************************
641 *
642 * Function         BTM_CancelInquiry
643 *
644 * Description      This function cancels an inquiry if active
645 *
646 * Returns          BTM_SUCCESS if successful
647 *                  BTM_NO_RESOURCES if could not allocate a message buffer
648 *                  BTM_WRONG_MODE if the device is not up.
649 *
650 ******************************************************************************/
651tBTM_STATUS BTM_CancelInquiry(void) {
652  tBTM_STATUS status = BTM_SUCCESS;
653  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
654#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
655  uint8_t active_mode = p_inq->inq_active;
656#endif
657  BTM_TRACE_API("BTM_CancelInquiry called");
658
659  /*** Make sure the device is ready ***/
660  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
661
662  /* Only cancel if not in periodic mode, otherwise the caller should call
663   * BTM_CancelPeriodicMode */
664  if ((p_inq->inq_active & BTM_INQUIRY_ACTIVE_MASK) != 0 &&
665      (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))) {
666    p_inq->inq_active = BTM_INQUIRY_INACTIVE;
667    p_inq->state = BTM_INQ_INACTIVE_STATE;
668    p_inq->p_inq_results_cb =
669        (tBTM_INQ_RESULTS_CB*)NULL; /* Do not notify caller anymore */
670    p_inq->p_inq_cmpl_cb =
671        (tBTM_CMPL_CB*)NULL; /* Do not notify caller anymore */
672
673    /* If the event filter is in progress, mark it so that the processing of the
674       return
675        event will be ignored */
676    if (p_inq->inqfilt_active) {
677      p_inq->inqfilt_active = false;
678      p_inq->pending_filt_complete_event++;
679    }
680    /* Initiate the cancel inquiry */
681    else {
682      if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
683#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
684          && (active_mode & BTM_BR_INQUIRY_MASK)
685#endif
686              ) {
687        btsnd_hcic_inq_cancel();
688      }
689      if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
690#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
691          && (active_mode & BTM_BLE_INQ_ACTIVE_MASK)
692#endif
693              )
694        btm_ble_stop_inquiry();
695    }
696
697    /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
698     * and then send the BUSY_LEVEL event
699     * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
700     */
701
702    p_inq->inq_counter++;
703    btm_clr_inq_result_flt();
704  }
705
706  return (status);
707}
708
709/*******************************************************************************
710 *
711 * Function         BTM_StartInquiry
712 *
713 * Description      This function is called to start an inquiry.
714 *
715 * Parameters:      p_inqparms - pointer to the inquiry information
716 *                      mode - GENERAL or LIMITED inquiry, BR/LE bit mask
717 *                             seperately
718 *                      duration - length in 1.28 sec intervals (If '0', the
719 *                                 inquiry is CANCELLED)
720 *                      max_resps - maximum amount of devices to search for
721 *                                  before ending the inquiry
722 *                      filter_cond_type - BTM_CLR_INQUIRY_FILTER,
723 *                                         BTM_FILTER_COND_DEVICE_CLASS, or
724 *                                         BTM_FILTER_COND_BD_ADDR
725 *                      filter_cond - value for the filter (based on
726 *                                                          filter_cond_type)
727 *
728 *                  p_results_cb   - Pointer to the callback routine which gets
729 *                                called upon receipt of an inquiry result. If
730 *                                this field is NULL, the application is not
731 *                                notified.
732 *
733 *                  p_cmpl_cb   - Pointer to the callback routine which gets
734 *                                called upon completion.  If this field is
735 *                                NULL, the application is not notified when
736 *                                completed.
737 * Returns          tBTM_STATUS
738 *                  BTM_CMD_STARTED if successfully initiated
739 *                  BTM_BUSY if already in progress
740 *                  BTM_ILLEGAL_VALUE if parameter(s) are out of range
741 *                  BTM_NO_RESOURCES if could not allocate resources to start
742 *                                   the command
743 *                  BTM_WRONG_MODE if the device is not up.
744 *
745 ******************************************************************************/
746tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
747                             tBTM_INQ_RESULTS_CB* p_results_cb,
748                             tBTM_CMPL_CB* p_cmpl_cb) {
749  tBTM_STATUS status = BTM_CMD_STARTED;
750  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
751
752  BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
753                p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
754                p_inqparms->filter_cond_type);
755
756  /* Only one active inquiry is allowed in this implementation.
757     Also do not allow an inquiry if the inquiry filter is being updated */
758  if (p_inq->inq_active || p_inq->inqfilt_active) {
759    /*check if LE observe is already running*/
760    if (p_inq->scan_type == INQ_LE_OBSERVE &&
761        p_inq->p_inq_ble_results_cb != NULL) {
762      BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
763      p_inq->scan_type = INQ_GENERAL;
764      p_inq->inq_active = BTM_INQUIRY_INACTIVE;
765      btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
766      btm_send_hci_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
767    } else {
768      return (BTM_BUSY);
769      BTM_TRACE_API("BTM_StartInquiry: return BUSY");
770    }
771  } else
772    p_inq->scan_type = INQ_GENERAL;
773
774  /*** Make sure the device is ready ***/
775  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
776
777  if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
778      (p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
779      (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
780      (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY)
781    return (BTM_ILLEGAL_VALUE);
782
783#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
784  if (p_inq->next_state == BTM_FINISH) return BTM_ILLEGAL_VALUE;
785#endif
786
787  /* Save the inquiry parameters to be used upon the completion of
788   * setting/clearing the inquiry filter */
789  p_inq->inqparms = *p_inqparms;
790
791  /* Initialize the inquiry variables */
792  p_inq->state = BTM_INQ_ACTIVE_STATE;
793  p_inq->p_inq_cmpl_cb = p_cmpl_cb;
794  p_inq->p_inq_results_cb = p_results_cb;
795  p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
796  p_inq->inq_active = p_inqparms->mode;
797
798  BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
799                  p_inq->inq_active);
800
801/* interleave scan minimal conditions */
802#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
803
804  /* check if both modes are present */
805  if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) &&
806      (p_inqparms->mode & BTM_BR_INQUIRY_MASK)) {
807    BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
808    p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state];
809    p_inq->inqparms.duration = p_inqparms->duration;
810  } else {
811    BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x",
812                  p_inqparms->mode);
813    p_inq->next_state = BTM_NO_INTERLEAVING;
814  }
815#endif
816
817  /* start LE inquiry here if requested */
818  if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
819#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
820      &&
821      (p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO ||
822       p_inq->next_state == BTM_NO_INTERLEAVING)
823#endif
824          )
825
826  {
827#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
828    p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
829    BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
830                  p_inqparms->duration,
831                  (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
832#endif
833    if (!controller_get_interface()->supports_ble()) {
834      p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
835      status = BTM_ILLEGAL_VALUE;
836    }
837    /* BLE for now does not support filter condition for inquiry */
838    else {
839      status = btm_ble_start_inquiry(
840          (uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
841          p_inqparms->duration);
842      if (status != BTM_CMD_STARTED) {
843        BTM_TRACE_ERROR("Err Starting LE Inquiry.");
844        p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
845      }
846    }
847#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
848    p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
849#endif
850
851#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
852    if (p_inq->next_state == BTM_NO_INTERLEAVING) {
853      p_inq->next_state = BTM_FINISH;
854    } else {
855      BTM_TRACE_API(
856          "BTM:Interleaving: started LE scan, Advancing to next state: %d",
857          p_inq->next_state + 1);
858      p_inq->next_state += 1;
859    }
860    /* reset next_state if status <> BTM_Started */
861    if (status != BTM_CMD_STARTED) p_inq->next_state = BTM_BR_ONE;
862
863    /* if interleave scan..return here */
864    return status;
865#endif
866
867    BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
868  }
869
870  /* we're done with this routine if BR/EDR inquiry is not desired. */
871  if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
872    return status;
873
874/* BR/EDR inquiry portion */
875#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
876  if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO ||
877       p_inq->next_state == BTM_NO_INTERLEAVING)) {
878    p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
879#endif
880    /* If a filter is specified, then save it for later and clear the current
881       filter.
882       The setting of the filter is done upon completion of clearing of the
883       previous
884       filter.
885    */
886    switch (p_inqparms->filter_cond_type) {
887      case BTM_CLR_INQUIRY_FILTER:
888        p_inq->state = BTM_INQ_SET_FILT_STATE;
889        break;
890
891      case BTM_FILTER_COND_DEVICE_CLASS:
892      case BTM_FILTER_COND_BD_ADDR:
893        /* The filter is not being used so simply clear it;
894            the inquiry can start after this operation */
895        p_inq->state = BTM_INQ_CLR_FILT_STATE;
896        p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
897        /* =============>>>> adding LE filtering here ????? */
898        break;
899
900      default:
901        return (BTM_ILLEGAL_VALUE);
902    }
903
904    /* Before beginning the inquiry the current filter must be cleared, so
905     * initiate the command */
906    status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
907                                      &p_inqparms->filter_cond);
908    if (status != BTM_CMD_STARTED) p_inq->state = BTM_INQ_INACTIVE_STATE;
909
910#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
911    if (p_inq->next_state == BTM_NO_INTERLEAVING)
912      p_inq->next_state = BTM_FINISH;
913    else {
914      BTM_TRACE_API(
915          "BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
916          p_inq->next_state + 1);
917      p_inq->next_state += 1;
918    }
919  }
920  if (status != BTM_CMD_STARTED) {
921    /* Some error beginning the scan process.
922       Reset the next_state parameter.. Do we need to reset the inq_active also?
923    */
924    BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x",
925                  status);
926    p_inq->next_state = BTM_BR_ONE;
927  }
928#endif
929
930  return (status);
931}
932
933/*******************************************************************************
934 *
935 * Function         BTM_ReadRemoteDeviceName
936 *
937 * Description      This function initiates a remote device HCI command to the
938 *                  controller and calls the callback when the process has
939 *                  completed.
940 *
941 * Input Params:    remote_bda      - device address of name to retrieve
942 *                  p_cb            - callback function called when
943 *                                    BTM_CMD_STARTED is returned.
944 *                                    A pointer to tBTM_REMOTE_DEV_NAME is
945 *                                    passed to the callback.
946 *
947 * Returns
948 *                  BTM_CMD_STARTED is returned if the request was successfully
949 *                                  sent to HCI.
950 *                  BTM_BUSY if already in progress
951 *                  BTM_UNKNOWN_ADDR if device address is bad
952 *                  BTM_NO_RESOURCES if could not allocate resources to start
953 *                                   the command
954 *                  BTM_WRONG_MODE if the device is not up.
955 *
956 ******************************************************************************/
957tBTM_STATUS BTM_ReadRemoteDeviceName(BD_ADDR remote_bda, tBTM_CMPL_CB* p_cb,
958                                     tBT_TRANSPORT transport) {
959  BTM_TRACE_API("%s: bd addr [%02x%02x%02x%02x%02x%02x]", __func__,
960                remote_bda[0], remote_bda[1], remote_bda[2], remote_bda[3],
961                remote_bda[4], remote_bda[5]);
962  /* Use LE transport when LE is the only available option */
963  if (transport == BT_TRANSPORT_LE) {
964    return btm_ble_read_remote_name(remote_bda, p_cb);
965  }
966  /* Use classic transport for BR/EDR and Dual Mode devices */
967  return btm_initiate_rem_name(remote_bda, BTM_RMT_NAME_EXT,
968                               BTM_EXT_RMT_NAME_TIMEOUT_MS, p_cb);
969}
970
971/*******************************************************************************
972 *
973 * Function         BTM_CancelRemoteDeviceName
974 *
975 * Description      This function initiates the cancel request for the specified
976 *                  remote device.
977 *
978 * Input Params:    None
979 *
980 * Returns
981 *                  BTM_CMD_STARTED is returned if the request was successfully
982 *                                  sent to HCI.
983 *                  BTM_NO_RESOURCES if could not allocate resources to start
984 *                                   the command
985 *                  BTM_WRONG_MODE if there is not an active remote name
986 *                                 request.
987 *
988 ******************************************************************************/
989tBTM_STATUS BTM_CancelRemoteDeviceName(void) {
990  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
991
992  BTM_TRACE_API("BTM_CancelRemoteDeviceName()");
993
994  /* Make sure there is not already one in progress */
995  if (p_inq->remname_active) {
996    if (BTM_UseLeLink(p_inq->remname_bda)) {
997      if (btm_ble_cancel_remote_name(p_inq->remname_bda))
998        return (BTM_CMD_STARTED);
999      else
1000        return (BTM_UNKNOWN_ADDR);
1001    } else
1002      btsnd_hcic_rmt_name_req_cancel(p_inq->remname_bda);
1003    return (BTM_CMD_STARTED);
1004  } else
1005    return (BTM_WRONG_MODE);
1006}
1007
1008/*******************************************************************************
1009 *
1010 * Function         BTM_InqDbRead
1011 *
1012 * Description      This function looks through the inquiry database for a match
1013 *                  based on Bluetooth Device Address. This is the application's
1014 *                  interface to get the inquiry details of a specific BD
1015 *                  address.
1016 *
1017 * Returns          pointer to entry, or NULL if not found
1018 *
1019 ******************************************************************************/
1020tBTM_INQ_INFO* BTM_InqDbRead(const BD_ADDR p_bda) {
1021  BTM_TRACE_API("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]", p_bda[0],
1022                p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
1023
1024  tINQ_DB_ENT* p_ent = btm_inq_db_find(p_bda);
1025  if (!p_ent) return NULL;
1026
1027  return &p_ent->inq_info;
1028}
1029
1030/*******************************************************************************
1031 *
1032 * Function         BTM_InqDbFirst
1033 *
1034 * Description      This function looks through the inquiry database for the
1035 *                  first used entry, and returns that. This is used in
1036 *                  conjunction with
1037 *                  BTM_InqDbNext by applications as a way to walk through the
1038 *                  inquiry database.
1039 *
1040 * Returns          pointer to first in-use entry, or NULL if DB is empty
1041 *
1042 ******************************************************************************/
1043tBTM_INQ_INFO* BTM_InqDbFirst(void) {
1044  uint16_t xx;
1045  tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1046
1047  for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1048    if (p_ent->in_use) return (&p_ent->inq_info);
1049  }
1050
1051  /* If here, no used entry found */
1052  return ((tBTM_INQ_INFO*)NULL);
1053}
1054
1055/*******************************************************************************
1056 *
1057 * Function         BTM_InqDbNext
1058 *
1059 * Description      This function looks through the inquiry database for the
1060 *                  next used entry, and returns that.  If the input parameter
1061 *                  is NULL, the first entry is returned.
1062 *
1063 * Returns          pointer to next in-use entry, or NULL if no more found.
1064 *
1065 ******************************************************************************/
1066tBTM_INQ_INFO* BTM_InqDbNext(tBTM_INQ_INFO* p_cur) {
1067  tINQ_DB_ENT* p_ent;
1068  uint16_t inx;
1069
1070  if (p_cur) {
1071    p_ent = (tINQ_DB_ENT*)((uint8_t*)p_cur - offsetof(tINQ_DB_ENT, inq_info));
1072    inx = (uint16_t)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1073
1074    for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE;
1075         inx++, p_ent++) {
1076      if (p_ent->in_use) return (&p_ent->inq_info);
1077    }
1078
1079    /* If here, more entries found */
1080    return ((tBTM_INQ_INFO*)NULL);
1081  } else
1082    return (BTM_InqDbFirst());
1083}
1084
1085/*******************************************************************************
1086 *
1087 * Function         BTM_ClearInqDb
1088 *
1089 * Description      This function is called to clear out a device or all devices
1090 *                  from the inquiry database.
1091 *
1092 * Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1093 *                                              (NULL clears all entries)
1094 *
1095 * Returns          BTM_BUSY if an inquiry, get remote name, or event filter
1096 *                          is active, otherwise BTM_SUCCESS
1097 *
1098 ******************************************************************************/
1099tBTM_STATUS BTM_ClearInqDb(BD_ADDR p_bda) {
1100  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1101
1102  /* If an inquiry or remote name is in progress return busy */
1103  if (p_inq->inq_active != BTM_INQUIRY_INACTIVE || p_inq->inqfilt_active)
1104    return (BTM_BUSY);
1105
1106  btm_clr_inq_db(p_bda);
1107
1108  return (BTM_SUCCESS);
1109}
1110
1111/*******************************************************************************
1112 *
1113 * Function         BTM_ReadInquiryRspTxPower
1114 *
1115 * Description      This command will read the inquiry Transmit Power level used
1116 *                  to transmit the FHS and EIR data packets. This can be used
1117 *                  directly in the Tx Power Level EIR data type.
1118 *
1119 * Returns          BTM_SUCCESS if successful
1120 *
1121 ******************************************************************************/
1122tBTM_STATUS BTM_ReadInquiryRspTxPower(tBTM_CMPL_CB* p_cb) {
1123  if (btm_cb.devcb.p_inq_tx_power_cmpl_cb) return (BTM_BUSY);
1124
1125  btm_cb.devcb.p_inq_tx_power_cmpl_cb = p_cb;
1126  alarm_set_on_queue(btm_cb.devcb.read_inq_tx_power_timer,
1127                     BTM_INQ_REPLY_TIMEOUT_MS, btm_read_inq_tx_power_timeout,
1128                     NULL, btu_general_alarm_queue);
1129
1130  btsnd_hcic_read_inq_tx_power();
1131  return (BTM_CMD_STARTED);
1132}
1133
1134/*******************************************************************************
1135 *******************************************************************************
1136 *                                                                            **
1137 *                    BTM Internal Inquiry Functions                          **
1138 *                                                                            **
1139 *******************************************************************************
1140 ******************************************************************************/
1141/*******************************************************************************
1142 *
1143 * Function         btm_inq_db_reset
1144 *
1145 * Description      This function is called at at reset to clear the inquiry
1146 *                  database & pending callback.
1147 *
1148 * Returns          void
1149 *
1150 ******************************************************************************/
1151void btm_inq_db_reset(void) {
1152  tBTM_REMOTE_DEV_NAME rem_name;
1153  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1154  uint8_t num_responses;
1155  uint8_t temp_inq_active;
1156  tBTM_STATUS status;
1157
1158  /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
1159  if (p_inq->inq_active != BTM_INQUIRY_INACTIVE) {
1160    temp_inq_active = p_inq->inq_active; /* Save so state can change BEFORE
1161                                                callback is called */
1162    p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1163
1164    /* If not a periodic inquiry, the complete callback must be called to notify
1165     * caller */
1166    if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
1167        temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE) {
1168      if (p_inq->p_inq_cmpl_cb) {
1169        num_responses = 0;
1170        (*p_inq->p_inq_cmpl_cb)(&num_responses);
1171      }
1172    }
1173  }
1174
1175  /* Cancel a remote name request if active, and notify the caller (if waiting)
1176   */
1177  if (p_inq->remname_active) {
1178    alarm_cancel(p_inq->remote_name_timer);
1179    p_inq->remname_active = false;
1180    memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
1181
1182    if (p_inq->p_remname_cmpl_cb) {
1183      rem_name.status = BTM_DEV_RESET;
1184
1185      (*p_inq->p_remname_cmpl_cb)(&rem_name);
1186      p_inq->p_remname_cmpl_cb = NULL;
1187    }
1188  }
1189
1190  /* Cancel an inquiry filter request if active, and notify the caller (if
1191   * waiting) */
1192  if (p_inq->inqfilt_active) {
1193    p_inq->inqfilt_active = false;
1194
1195    if (p_inq->p_inqfilter_cmpl_cb) {
1196      status = BTM_DEV_RESET;
1197      (*p_inq->p_inqfilter_cmpl_cb)(&status);
1198    }
1199  }
1200
1201  p_inq->state = BTM_INQ_INACTIVE_STATE;
1202  p_inq->pending_filt_complete_event = 0;
1203  p_inq->p_inq_results_cb = NULL;
1204  btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
1205  btm_clr_inq_result_flt();
1206
1207  p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1208  p_inq->connectable_mode = BTM_NON_CONNECTABLE;
1209  p_inq->page_scan_type = BTM_SCAN_TYPE_STANDARD;
1210  p_inq->inq_scan_type = BTM_SCAN_TYPE_STANDARD;
1211
1212  p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1213  p_inq->connectable_mode |= BTM_BLE_NON_CONNECTABLE;
1214  return;
1215}
1216
1217/*******************************************************************************
1218 *
1219 * Function         btm_inq_db_init
1220 *
1221 * Description      This function is called at startup to initialize the inquiry
1222 *                  database.
1223 *
1224 * Returns          void
1225 *
1226 ******************************************************************************/
1227void btm_inq_db_init(void) {
1228  alarm_free(btm_cb.btm_inq_vars.remote_name_timer);
1229  btm_cb.btm_inq_vars.remote_name_timer =
1230      alarm_new("btm_inq.remote_name_timer");
1231  btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1232}
1233
1234/*******************************************************************************
1235 *
1236 * Function         btm_inq_stop_on_ssp
1237 *
1238 * Description      This function is called on incoming SSP
1239 *
1240 * Returns          void
1241 *
1242 ******************************************************************************/
1243void btm_inq_stop_on_ssp(void) {
1244  uint8_t normal_active =
1245      (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1246
1247#if (BTM_INQ_DEBUG == TRUE)
1248  BTM_TRACE_DEBUG(
1249      "btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d "
1250      "inqfilt_active:%d",
1251      btm_cb.btm_inq_vars.no_inc_ssp, btm_cb.btm_inq_vars.inq_active,
1252      btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1253#endif
1254  if (btm_cb.btm_inq_vars.no_inc_ssp) {
1255    if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1256      if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1257        BTM_CancelPeriodicInquiry();
1258      } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1259        /* can not call BTM_CancelInquiry() here. We need to report inquiry
1260         * complete evt */
1261        btsnd_hcic_inq_cancel();
1262      }
1263    }
1264    /* do not allow inquiry to start */
1265    btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1266  }
1267}
1268
1269/*******************************************************************************
1270 *
1271 * Function         btm_inq_clear_ssp
1272 *
1273 * Description      This function is called when pairing_state becomes idle
1274 *
1275 * Returns          void
1276 *
1277 ******************************************************************************/
1278void btm_inq_clear_ssp(void) {
1279  btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1280}
1281
1282/*******************************************************************************
1283 *
1284 * Function         btm_clr_inq_db
1285 *
1286 * Description      This function is called to clear out a device or all devices
1287 *                  from the inquiry database.
1288 *
1289 * Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1290 *                                              (NULL clears all entries)
1291 *
1292 * Returns          void
1293 *
1294 ******************************************************************************/
1295void btm_clr_inq_db(BD_ADDR p_bda) {
1296  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1297  tINQ_DB_ENT* p_ent = p_inq->inq_db;
1298  uint16_t xx;
1299
1300#if (BTM_INQ_DEBUG == TRUE)
1301  BTM_TRACE_DEBUG("btm_clr_inq_db: inq_active:0x%x state:%d",
1302                  btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1303#endif
1304  for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1305    if (p_ent->in_use) {
1306      /* If this is the specified BD_ADDR or clearing all devices */
1307      if (p_bda == NULL || (!memcmp(p_ent->inq_info.results.remote_bd_addr,
1308                                    p_bda, BD_ADDR_LEN))) {
1309        p_ent->in_use = false;
1310      }
1311    }
1312  }
1313#if (BTM_INQ_DEBUG == TRUE)
1314  BTM_TRACE_DEBUG("inq_active:0x%x state:%d", btm_cb.btm_inq_vars.inq_active,
1315                  btm_cb.btm_inq_vars.state);
1316#endif
1317}
1318
1319/*******************************************************************************
1320 *
1321 * Function         btm_clr_inq_result_flt
1322 *
1323 * Description      This function looks through the bdaddr database for a match
1324 *                  based on Bluetooth Device Address
1325 *
1326 * Returns          true if found, else false (new entry)
1327 *
1328 ******************************************************************************/
1329static void btm_clr_inq_result_flt(void) {
1330  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1331
1332  osi_free_and_reset((void**)&p_inq->p_bd_db);
1333  p_inq->num_bd_entries = 0;
1334  p_inq->max_bd_entries = 0;
1335}
1336
1337/*******************************************************************************
1338 *
1339 * Function         btm_inq_find_bdaddr
1340 *
1341 * Description      This function looks through the bdaddr database for a match
1342 *                  based on Bluetooth Device Address
1343 *
1344 * Returns          true if found, else false (new entry)
1345 *
1346 ******************************************************************************/
1347bool btm_inq_find_bdaddr(BD_ADDR p_bda) {
1348  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1349  tINQ_BDADDR* p_db = &p_inq->p_bd_db[0];
1350  uint16_t xx;
1351
1352  /* Don't bother searching, database doesn't exist or periodic mode */
1353  if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db)
1354    return (false);
1355
1356  for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1357    if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN) &&
1358        p_db->inq_count == p_inq->inq_counter)
1359      return (true);
1360  }
1361
1362  if (xx < p_inq->max_bd_entries) {
1363    p_db->inq_count = p_inq->inq_counter;
1364    memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1365    p_inq->num_bd_entries++;
1366  }
1367
1368  /* If here, New Entry */
1369  return (false);
1370}
1371
1372/*******************************************************************************
1373 *
1374 * Function         btm_inq_db_find
1375 *
1376 * Description      This function looks through the inquiry database for a match
1377 *                  based on Bluetooth Device Address
1378 *
1379 * Returns          pointer to entry, or NULL if not found
1380 *
1381 ******************************************************************************/
1382tINQ_DB_ENT* btm_inq_db_find(const BD_ADDR p_bda) {
1383  uint16_t xx;
1384  tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1385
1386  for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1387    if ((p_ent->in_use) &&
1388        (!memcmp(p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1389      return (p_ent);
1390  }
1391
1392  /* If here, not found */
1393  return (NULL);
1394}
1395
1396/*******************************************************************************
1397 *
1398 * Function         btm_inq_db_new
1399 *
1400 * Description      This function looks through the inquiry database for an
1401 *                  unused entry. If no entry is free, it allocates the oldest
1402 *                  entry.
1403 *
1404 * Returns          pointer to entry
1405 *
1406 ******************************************************************************/
1407tINQ_DB_ENT* btm_inq_db_new(BD_ADDR p_bda) {
1408  uint16_t xx;
1409  tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1410  tINQ_DB_ENT* p_old = btm_cb.btm_inq_vars.inq_db;
1411  uint32_t ot = 0xFFFFFFFF;
1412
1413  for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1414    if (!p_ent->in_use) {
1415      memset(p_ent, 0, sizeof(tINQ_DB_ENT));
1416      memcpy(p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1417      p_ent->in_use = true;
1418
1419      return (p_ent);
1420    }
1421
1422    if (p_ent->time_of_resp < ot) {
1423      p_old = p_ent;
1424      ot = p_ent->time_of_resp;
1425    }
1426  }
1427
1428  /* If here, no free entry found. Return the oldest. */
1429
1430  memset(p_old, 0, sizeof(tINQ_DB_ENT));
1431  memcpy(p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1432  p_old->in_use = true;
1433
1434  return (p_old);
1435}
1436
1437/*******************************************************************************
1438 *
1439 * Function         btm_set_inq_event_filter
1440 *
1441 * Description      This function is called to set the inquiry event filter.
1442 *                  It is called by either internally, or by the external API
1443 *                  function (BTM_SetInqEventFilter).  It is used internally as
1444 *                  part of the inquiry processing.
1445 *
1446 * Input Params:
1447 *                  filter_cond_type - this is the type of inquiry filter to
1448 *                                     apply:
1449 *                          BTM_FILTER_COND_DEVICE_CLASS,
1450 *                          BTM_FILTER_COND_BD_ADDR, or
1451 *                          BTM_CLR_INQUIRY_FILTER
1452 *
1453 *                  p_filt_cond - this is either a BD_ADDR or DEV_CLASS
1454 *                                depending on the filter_cond_type
1455 *                                (See section 4.7.3 of Core Spec 1.0b).
1456 *
1457 * Returns          BTM_CMD_STARTED if successfully initiated
1458 *                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
1459 *                  BTM_ILLEGAL_VALUE if a bad parameter was detected
1460 *
1461 ******************************************************************************/
1462static tBTM_STATUS btm_set_inq_event_filter(uint8_t filter_cond_type,
1463                                            tBTM_INQ_FILT_COND* p_filt_cond) {
1464  uint8_t condition_length = DEV_CLASS_LEN * 2;
1465  uint8_t condition_buf[DEV_CLASS_LEN * 2];
1466  uint8_t* p_cond = condition_buf; /* points to the condition to pass to HCI */
1467
1468#if (BTM_INQ_DEBUG == TRUE)
1469  BTM_TRACE_DEBUG(
1470      "btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
1471      filter_cond_type);
1472  BTM_TRACE_DEBUG(
1473      "                       condition [%02x%02x%02x %02x%02x%02x]",
1474      p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1],
1475      p_filt_cond->bdaddr_cond[2], p_filt_cond->bdaddr_cond[3],
1476      p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1477#endif
1478
1479  /* Load the correct filter condition to pass to the lower layer */
1480  switch (filter_cond_type) {
1481    case BTM_FILTER_COND_DEVICE_CLASS:
1482      /* copy the device class and device class fields into contiguous memory to
1483       * send to HCI */
1484      memcpy(condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1485      memcpy(&condition_buf[DEV_CLASS_LEN],
1486             p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1487
1488      /* condition length should already be set as the default */
1489      break;
1490
1491    case BTM_FILTER_COND_BD_ADDR:
1492      p_cond = p_filt_cond->bdaddr_cond;
1493
1494      /* condition length should already be set as the default */
1495      break;
1496
1497    case BTM_CLR_INQUIRY_FILTER:
1498      condition_length = 0;
1499      break;
1500
1501    default:
1502      return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1503  }
1504
1505  btm_cb.btm_inq_vars.inqfilt_active = true;
1506
1507  /* Filter the inquiry results for the specified condition type and value */
1508  btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1509                              p_cond, condition_length);
1510  return (BTM_CMD_STARTED);
1511}
1512
1513/*******************************************************************************
1514 *
1515 * Function         btm_event_filter_complete
1516 *
1517 * Description      This function is called when a set event filter has
1518 *                  completed.
1519 *                  Note: This routine currently only handles inquiry filters.
1520 *                      Connection filters are ignored for now.
1521 *
1522 * Returns          void
1523 *
1524 ******************************************************************************/
1525void btm_event_filter_complete(uint8_t* p) {
1526  uint8_t hci_status;
1527  tBTM_STATUS status;
1528  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1529  tBTM_CMPL_CB* p_cb = p_inq->p_inqfilter_cmpl_cb;
1530
1531#if (BTM_INQ_DEBUG == TRUE)
1532  BTM_TRACE_DEBUG(
1533      "btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d",
1534      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1535      btm_cb.btm_inq_vars.inqfilt_active);
1536#endif
1537  /* If the filter complete event is from an old or cancelled request, ignore it
1538   */
1539  if (p_inq->pending_filt_complete_event) {
1540    p_inq->pending_filt_complete_event--;
1541    return;
1542  }
1543
1544  /* Only process the inquiry filter; Ignore the connection filter until it
1545     is used by the upper layers */
1546  if (p_inq->inqfilt_active == true) {
1547    /* Extract the returned status from the buffer */
1548    STREAM_TO_UINT8(hci_status, p);
1549    if (hci_status != HCI_SUCCESS) {
1550      /* If standalone operation, return the error status; if embedded in the
1551       * inquiry, continue the inquiry */
1552      BTM_TRACE_WARNING(
1553          "BTM Warning: Set Event Filter Failed (HCI returned 0x%x)",
1554          hci_status);
1555      status = BTM_ERR_PROCESSING;
1556    } else
1557      status = BTM_SUCCESS;
1558
1559    /* If the set filter was initiated externally (via BTM_SetInqEventFilter),
1560       call the
1561       callback function to notify the initiator that it has completed */
1562    if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1563      p_inq->inqfilt_active = false;
1564      if (p_cb) (*p_cb)(&status);
1565    } else /* An inquiry is active (the set filter command was internally
1566              generated),
1567              process the next state of the process (Set a new filter or start
1568              the inquiry). */
1569    {
1570      if (status != BTM_SUCCESS) {
1571        /* Process the inquiry complete (Error Status) */
1572        btm_process_inq_complete(
1573            BTM_ERR_PROCESSING,
1574            (uint8_t)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1575
1576        /* btm_process_inq_complete() does not restore the following settings on
1577         * periodic inquiry */
1578        p_inq->inqfilt_active = false;
1579        p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1580        p_inq->state = BTM_INQ_INACTIVE_STATE;
1581
1582        return;
1583      }
1584
1585      /* Check to see if a new filter needs to be set up */
1586      if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1587        status = btm_set_inq_event_filter(p_inq->inqparms.filter_cond_type,
1588                                          &p_inq->inqparms.filter_cond);
1589        if (status == BTM_CMD_STARTED) {
1590          p_inq->state = BTM_INQ_SET_FILT_STATE;
1591        } else /* Error setting the filter: Call the initiator's callback
1592                  function to indicate a failure */
1593        {
1594          p_inq->inqfilt_active = false;
1595
1596          /* Process the inquiry complete (Error Status) */
1597          btm_process_inq_complete(
1598              BTM_ERR_PROCESSING,
1599              (uint8_t)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1600        }
1601      } else /* Initiate the Inquiry or Periodic Inquiry */
1602      {
1603        p_inq->state = BTM_INQ_ACTIVE_STATE;
1604        p_inq->inqfilt_active = false;
1605        btm_initiate_inquiry(p_inq);
1606      }
1607    }
1608  }
1609}
1610
1611/*******************************************************************************
1612 *
1613 * Function         btm_initiate_inquiry
1614 *
1615 * Description      This function is called to start an inquiry or periodic
1616 *                  inquiry upon completion of the setting and/or clearing of
1617 *                  the inquiry filter.
1618 *
1619 * Inputs:          p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry
1620 *                                                information
1621 *                      mode - GENERAL or LIMITED inquiry
1622 *                      duration - length in 1.28 sec intervals
1623 *                                 (If '0', the inquiry is CANCELLED)
1624 *                      max_resps - maximum amount of devices to search for
1625 *                                  before ending the inquiry
1626 *                      filter_cond_type - BTM_CLR_INQUIRY_FILTER,
1627 *                                         BTM_FILTER_COND_DEVICE_CLASS, or
1628 *                                         BTM_FILTER_COND_BD_ADDR
1629 *                      filter_cond - value for the filter
1630 *                                   (based on filter_cond_type)
1631 *
1632 * Returns          If an error occurs the initiator's callback is called with
1633 *                  the error status.
1634 *
1635 ******************************************************************************/
1636static void btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST* p_inq) {
1637  const LAP* lap;
1638  tBTM_INQ_PARMS* p_inqparms = &p_inq->inqparms;
1639
1640#if (BTM_INQ_DEBUG == TRUE)
1641  BTM_TRACE_DEBUG(
1642      "btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d",
1643      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1644      btm_cb.btm_inq_vars.inqfilt_active);
1645#endif
1646  btm_acl_update_busy_level(BTM_BLI_INQ_EVT);
1647
1648  if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1649    btm_process_inq_complete(BTM_NO_RESOURCES,
1650                             (uint8_t)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1651    return;
1652  }
1653
1654  /* Make sure the number of responses doesn't overflow the database
1655   * configuration */
1656  p_inqparms->max_resps = (uint8_t)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE)
1657                                        ? p_inqparms->max_resps
1658                                        : BTM_INQ_DB_SIZE);
1659
1660  lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap
1661                                                         : &general_inq_lap;
1662
1663  if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1664    btsnd_hcic_per_inq_mode(p_inq->per_max_delay, p_inq->per_min_delay, *lap,
1665                            p_inqparms->duration, p_inqparms->max_resps);
1666  } else {
1667    btm_clr_inq_result_flt();
1668
1669    /* Allocate memory to hold bd_addrs responding */
1670    p_inq->p_bd_db = (tINQ_BDADDR*)osi_calloc(BT_DEFAULT_BUFFER_SIZE);
1671    p_inq->max_bd_entries =
1672        (uint16_t)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1673
1674    btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0);
1675  }
1676}
1677
1678/*******************************************************************************
1679 *
1680 * Function         btm_process_inq_results
1681 *
1682 * Description      This function is called when inquiry results are received
1683 *                  from the device. It updates the inquiry database. If the
1684 *                  inquiry database is full, the oldest entry is discarded.
1685 *
1686 * Parameters       inq_res_mode - BTM_INQ_RESULT_STANDARD
1687 *                                 BTM_INQ_RESULT_WITH_RSSI
1688 *                                 BTM_INQ_RESULT_EXTENDED
1689 *
1690 * Returns          void
1691 *
1692 ******************************************************************************/
1693void btm_process_inq_results(uint8_t* p, uint8_t inq_res_mode) {
1694  uint8_t num_resp, xx;
1695  BD_ADDR bda;
1696  tINQ_DB_ENT* p_i;
1697  tBTM_INQ_RESULTS* p_cur = NULL;
1698  bool is_new = true;
1699  bool update = false;
1700  int8_t i_rssi;
1701  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1702  tBTM_INQ_RESULTS_CB* p_inq_results_cb = p_inq->p_inq_results_cb;
1703  uint8_t page_scan_rep_mode = 0;
1704  uint8_t page_scan_per_mode = 0;
1705  uint8_t page_scan_mode = 0;
1706  uint8_t rssi = 0;
1707  DEV_CLASS dc;
1708  uint16_t clock_offset;
1709  uint8_t* p_eir_data = NULL;
1710
1711#if (BTM_INQ_DEBUG == TRUE)
1712  BTM_TRACE_DEBUG(
1713      "btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
1714      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1715      btm_cb.btm_inq_vars.inqfilt_active);
1716#endif
1717  /* Only process the results if the BR inquiry is still active */
1718  if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) return;
1719
1720  STREAM_TO_UINT8(num_resp, p);
1721
1722  if (inq_res_mode == BTM_INQ_RESULT_EXTENDED && (num_resp > 1)) {
1723    BTM_TRACE_ERROR("btm_process_inq_results() extended results (%d) > 1",
1724                    num_resp);
1725    return;
1726  }
1727
1728  for (xx = 0; xx < num_resp; xx++) {
1729    update = false;
1730    /* Extract inquiry results */
1731    STREAM_TO_BDADDR(bda, p);
1732    STREAM_TO_UINT8(page_scan_rep_mode, p);
1733    STREAM_TO_UINT8(page_scan_per_mode, p);
1734
1735    if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1736      STREAM_TO_UINT8(page_scan_mode, p);
1737    }
1738
1739    STREAM_TO_DEVCLASS(dc, p);
1740    STREAM_TO_UINT16(clock_offset, p);
1741    if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1742      STREAM_TO_UINT8(rssi, p);
1743    }
1744
1745    p_i = btm_inq_db_find(bda);
1746
1747    /* Only process the num_resp is smaller than max_resps.
1748       If results are queued to BTU task while canceling inquiry,
1749       or when more than one result is in this response, > max_resp
1750       responses could be processed which can confuse some apps
1751    */
1752    if (p_inq->inqparms.max_resps &&
1753        p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1754        /* new device response */
1755        &&
1756        (p_i == NULL ||
1757         /* exisiting device with BR/EDR info */
1758         (p_i &&
1759          (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0))) {
1760      /* BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring"); */
1761      return;
1762    }
1763
1764    /* Check if this address has already been processed for this inquiry */
1765    if (btm_inq_find_bdaddr(bda)) {
1766      /* BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]",
1767                      bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);*/
1768      /* By default suppose no update needed */
1769      i_rssi = (int8_t)rssi;
1770
1771      /* If this new RSSI is higher than the last one */
1772      if (p_inq->inqparms.report_dup && (rssi != 0) && p_i &&
1773          (i_rssi > p_i->inq_info.results.rssi ||
1774           p_i->inq_info.results.rssi == 0
1775           /* BR/EDR inquiry information update */
1776           ||
1777           (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)) {
1778        p_cur = &p_i->inq_info.results;
1779        BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);
1780        p_cur->rssi = i_rssi;
1781        update = true;
1782      }
1783      /* If we received a second Extended Inq Event for an already */
1784      /* discovered device, this is because for the first one EIR was not
1785         received */
1786      else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1787        p_cur = &p_i->inq_info.results;
1788        update = true;
1789      }
1790      /* If no update needed continue with next response (if any) */
1791      else
1792        continue;
1793    }
1794
1795    /* If existing entry, use that, else get a new one (possibly reusing the
1796     * oldest) */
1797    if (p_i == NULL) {
1798      p_i = btm_inq_db_new(bda);
1799      is_new = true;
1800    }
1801
1802    /* If an entry for the device already exists, overwrite it ONLY if it is
1803       from
1804       a previous inquiry. (Ignore it if it is a duplicate response from the
1805       same
1806       inquiry.
1807    */
1808    else if (p_i->inq_count == p_inq->inq_counter &&
1809             (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR))
1810      is_new = false;
1811
1812    /* keep updating RSSI to have latest value */
1813    if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
1814      p_i->inq_info.results.rssi = (int8_t)rssi;
1815    else
1816      p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1817
1818    if (is_new == true) {
1819      /* Save the info */
1820      p_cur = &p_i->inq_info.results;
1821      p_cur->page_scan_rep_mode = page_scan_rep_mode;
1822      p_cur->page_scan_per_mode = page_scan_per_mode;
1823      p_cur->page_scan_mode = page_scan_mode;
1824      p_cur->dev_class[0] = dc[0];
1825      p_cur->dev_class[1] = dc[1];
1826      p_cur->dev_class[2] = dc[2];
1827      p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1828
1829      p_i->time_of_resp = time_get_os_boottime_ms();
1830
1831      if (p_i->inq_count != p_inq->inq_counter)
1832        p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
1833
1834      p_cur->inq_result_type = BTM_INQ_RESULT_BR;
1835      if (p_i->inq_count != p_inq->inq_counter) {
1836        p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1837        p_i->scan_rsp = false;
1838      } else
1839        p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1840      p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
1841
1842      /* If the number of responses found and not unlimited, issue a cancel
1843       * inquiry */
1844      if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1845          p_inq->inqparms.max_resps &&
1846          p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps &&
1847          /* BLE scanning is active and received adv */
1848          ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1849            p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1850           (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)) {
1851        /*                BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling
1852         * inquiry..."); */
1853        btsnd_hcic_inq_cancel();
1854
1855        if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
1856          btm_ble_stop_inquiry();
1857        btm_acl_update_busy_level(BTM_BLI_INQ_DONE_EVT);
1858      }
1859      /* Initialize flag to false. This flag is set/used by application */
1860      p_i->inq_info.appl_knows_rem_name = false;
1861    }
1862
1863    if (is_new || update) {
1864      if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
1865        memset(p_cur->eir_uuid, 0,
1866               BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
1867        /* set bit map of UUID list from received EIR */
1868        btm_set_eir_uuid(p, p_cur);
1869        p_eir_data = p;
1870      } else
1871        p_eir_data = NULL;
1872
1873      /* If a callback is registered, call it with the results */
1874      if (p_inq_results_cb)
1875        (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data, 62);
1876    }
1877  }
1878}
1879
1880/*******************************************************************************
1881 *
1882 * Function         btm_sort_inq_result
1883 *
1884 * Description      This function is called when inquiry complete is received
1885 *                  from the device to sort inquiry results based on rssi.
1886 *
1887 * Returns          void
1888 *
1889 ******************************************************************************/
1890void btm_sort_inq_result(void) {
1891  uint8_t xx, yy, num_resp;
1892  tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1893  tINQ_DB_ENT* p_next = btm_cb.btm_inq_vars.inq_db + 1;
1894  int size;
1895  tINQ_DB_ENT* p_tmp = (tINQ_DB_ENT*)osi_malloc(sizeof(tINQ_DB_ENT));
1896
1897  num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE)
1898                 ? btm_cb.btm_inq_vars.inq_cmpl_info.num_resp
1899                 : BTM_INQ_DB_SIZE;
1900
1901  size = sizeof(tINQ_DB_ENT);
1902  for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
1903    for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
1904      if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
1905        memcpy(p_tmp, p_next, size);
1906        memcpy(p_next, p_ent, size);
1907        memcpy(p_ent, p_tmp, size);
1908      }
1909    }
1910  }
1911
1912  osi_free(p_tmp);
1913}
1914
1915/*******************************************************************************
1916 *
1917 * Function         btm_process_inq_complete
1918 *
1919 * Description      This function is called when inquiry complete is received
1920 *                  from the device.  Call the callback if not in periodic
1921 *                  inquiry mode AND it is not NULL
1922 *                  (The caller wants the event).
1923 *
1924 *                  The callback pass back the status and the number of
1925 *                  responses
1926 *
1927 * Returns          void
1928 *
1929 ******************************************************************************/
1930void btm_process_inq_complete(uint8_t status, uint8_t mode) {
1931  tBTM_CMPL_CB* p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
1932  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1933
1934#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
1935  /* inquiry inactive case happens when inquiry is cancelled.
1936     Make mode 0 for no further inquiries from the current inquiry process
1937  */
1938  if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH ||
1939      !p_inq->inq_active) {
1940    /* re-initialize for next inquiry request */
1941    p_inq->next_state = BTM_BR_ONE;
1942    /* make the mode 0 here */
1943    p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
1944  }
1945#endif
1946
1947#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
1948  p_inq->inqparms.mode &= ~(mode);
1949#endif
1950
1951  if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
1952    /*end of LE observe*/
1953    p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
1954    p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB*)NULL;
1955    p_inq->scan_type = INQ_NONE;
1956  }
1957
1958#if (BTM_INQ_DEBUG == TRUE)
1959  BTM_TRACE_DEBUG(
1960      "btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d",
1961      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1962      btm_cb.btm_inq_vars.inqfilt_active);
1963#endif
1964  btm_acl_update_busy_level(BTM_BLI_INQ_DONE_EVT);
1965  /* Ignore any stray or late complete messages if the inquiry is not active */
1966  if (p_inq->inq_active) {
1967    p_inq->inq_cmpl_info.status = (tBTM_STATUS)(
1968        (status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
1969
1970    /* Notify caller that the inquiry has completed; (periodic inquiries do not
1971     * send completion events */
1972    if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1973        p_inq->inqparms.mode == 0) {
1974      btm_clear_all_pending_le_entry();
1975      p_inq->state = BTM_INQ_INACTIVE_STATE;
1976
1977      /* Increment so the start of a next inquiry has a new count */
1978      p_inq->inq_counter++;
1979
1980      btm_clr_inq_result_flt();
1981
1982      if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
1983          controller_get_interface()->supports_rssi_with_inquiry_results()) {
1984        btm_sort_inq_result();
1985      }
1986
1987      /* Clear the results callback if set */
1988      p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
1989      p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1990      p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB*)NULL;
1991
1992      /* If we have a callback registered for inquiry complete, call it */
1993      BTM_TRACE_DEBUG("BTM Inq Compl Callback: status 0x%02x, num results %d",
1994                      p_inq->inq_cmpl_info.status,
1995                      p_inq->inq_cmpl_info.num_resp);
1996
1997      if (p_inq_cb) (p_inq_cb)((tBTM_INQUIRY_CMPL*)&p_inq->inq_cmpl_info);
1998    }
1999#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2000    if (p_inq->inqparms.mode != 0 &&
2001        !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
2002      /* make inquiry inactive for next iteration */
2003      p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2004      /* call the inquiry again */
2005      BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb,
2006                       p_inq->p_inq_cmpl_cb);
2007    }
2008#endif
2009  }
2010  if (p_inq->inqparms.mode == 0 &&
2011      p_inq->scan_type == INQ_GENERAL)  // this inquiry is complete
2012  {
2013    p_inq->scan_type = INQ_NONE;
2014    /* check if the LE observe is pending */
2015    if (p_inq->p_inq_ble_results_cb != NULL) {
2016      BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2017      BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb,
2018                     p_inq->p_inq_ble_cmpl_cb);
2019    }
2020  }
2021#if (BTM_INQ_DEBUG == TRUE)
2022  BTM_TRACE_DEBUG("inq_active:0x%x state:%d inqfilt_active:%d",
2023                  btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
2024                  btm_cb.btm_inq_vars.inqfilt_active);
2025#endif
2026}
2027
2028/*******************************************************************************
2029 *
2030 * Function         btm_process_cancel_complete
2031 *
2032 * Description      This function is called when inquiry cancel complete is
2033 *                  received from the device. This function will also call the
2034 *                  btm_process_inq_complete. This function is needed to
2035 *                  differentiate a cancel_cmpl_evt from the inq_cmpl_evt.
2036 *
2037 * Returns          void
2038 *
2039 ******************************************************************************/
2040void btm_process_cancel_complete(uint8_t status, uint8_t mode) {
2041  btm_acl_update_busy_level(BTM_BLI_INQ_CANCEL_EVT);
2042  btm_process_inq_complete(status, mode);
2043}
2044/*******************************************************************************
2045 *
2046 * Function         btm_initiate_rem_name
2047 *
2048 * Description      This function looks initiates a remote name request.  It is
2049 *                  called either by GAP or by the API call
2050 *                  BTM_ReadRemoteDeviceName.
2051 *
2052 * Input Params:    p_cb            - callback function called when
2053 *                                    BTM_CMD_STARTED is returned.
2054 *                                    A pointer to tBTM_REMOTE_DEV_NAME is
2055 *                                    passed to the callback.
2056 *
2057 * Returns
2058 *                  BTM_CMD_STARTED is returned if the request was sent to HCI.
2059 *                  BTM_BUSY if already in progress
2060 *                  BTM_NO_RESOURCES if could not allocate resources to start
2061 *                                   the command
2062 *                  BTM_WRONG_MODE if the device is not up.
2063 *
2064 ******************************************************************************/
2065tBTM_STATUS btm_initiate_rem_name(BD_ADDR remote_bda, uint8_t origin,
2066                                  period_ms_t timeout_ms, tBTM_CMPL_CB* p_cb) {
2067  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
2068
2069  /*** Make sure the device is ready ***/
2070  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
2071
2072  if (origin == BTM_RMT_NAME_SEC) {
2073    btsnd_hcic_rmt_name_req(remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2074                            HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2075    return BTM_CMD_STARTED;
2076  }
2077  /* Make sure there are no two remote name requests from external API in
2078     progress */
2079  else if (origin == BTM_RMT_NAME_EXT) {
2080    if (p_inq->remname_active) {
2081      return (BTM_BUSY);
2082    } else {
2083      /* If there is no remote name request running,call the callback function
2084       * and start timer */
2085      p_inq->p_remname_cmpl_cb = p_cb;
2086      memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2087
2088      alarm_set_on_queue(p_inq->remote_name_timer, timeout_ms,
2089                         btm_inq_remote_name_timer_timeout, NULL,
2090                         btu_general_alarm_queue);
2091
2092      /* If the database entry exists for the device, use its clock offset */
2093      tINQ_DB_ENT* p_i = btm_inq_db_find(remote_bda);
2094      if (p_i) {
2095        tBTM_INQ_INFO* p_cur = &p_i->inq_info;
2096        btsnd_hcic_rmt_name_req(
2097            remote_bda, p_cur->results.page_scan_rep_mode,
2098            p_cur->results.page_scan_mode,
2099            (uint16_t)(p_cur->results.clock_offset | BTM_CLOCK_OFFSET_VALID));
2100      } else {
2101        /* Otherwise use defaults and mark the clock offset as invalid */
2102        btsnd_hcic_rmt_name_req(remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2103                                HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2104      }
2105
2106      p_inq->remname_active = true;
2107      return BTM_CMD_STARTED;
2108    }
2109  } else {
2110    return BTM_ILLEGAL_VALUE;
2111  }
2112}
2113
2114/*******************************************************************************
2115 *
2116 * Function         btm_process_remote_name
2117 *
2118 * Description      This function is called when a remote name is received from
2119 *                  the device. If remote names are cached, it updates the
2120 *                  inquiry database.
2121 *
2122 * Returns          void
2123 *
2124 ******************************************************************************/
2125void btm_process_remote_name(BD_ADDR bda, BD_NAME bdn, uint16_t evt_len,
2126                             uint8_t hci_status) {
2127  tBTM_REMOTE_DEV_NAME rem_name;
2128  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
2129  tBTM_CMPL_CB* p_cb = p_inq->p_remname_cmpl_cb;
2130  uint8_t* p_n1;
2131
2132  uint16_t temp_evt_len;
2133
2134  if (bda != NULL) {
2135    BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x", bda[0], bda[1], bda[2],
2136                    bda[3], bda[4], bda[5]);
2137  }
2138
2139  BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x",
2140                  p_inq->remname_bda[0], p_inq->remname_bda[1],
2141                  p_inq->remname_bda[2], p_inq->remname_bda[3],
2142                  p_inq->remname_bda[4], p_inq->remname_bda[5]);
2143
2144  /* If the inquire BDA and remote DBA are the same, then stop the timer and set
2145   * the active to false */
2146  if ((p_inq->remname_active == true) &&
2147      (((bda != NULL) && (memcmp(bda, p_inq->remname_bda, BD_ADDR_LEN) == 0)) ||
2148       bda == NULL))
2149
2150  {
2151    if (BTM_UseLeLink(p_inq->remname_bda)) {
2152      if (hci_status == HCI_ERR_UNSPECIFIED)
2153        btm_ble_cancel_remote_name(p_inq->remname_bda);
2154    }
2155    alarm_cancel(p_inq->remote_name_timer);
2156    p_inq->remname_active = false;
2157    /* Clean up and return the status if the command was not successful */
2158    /* Note: If part of the inquiry, the name is not stored, and the    */
2159    /*       inquiry complete callback is called.                       */
2160
2161    if (hci_status == HCI_SUCCESS) {
2162      /* Copy the name from the data stream into the return structure */
2163      /* Note that even if it is not being returned, it is used as a  */
2164      /*      temporary buffer.                                       */
2165      p_n1 = (uint8_t*)rem_name.remote_bd_name;
2166      rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2167      rem_name.remote_bd_name[rem_name.length] = 0;
2168      rem_name.status = BTM_SUCCESS;
2169      temp_evt_len = rem_name.length;
2170
2171      while (temp_evt_len > 0) {
2172        *p_n1++ = *bdn++;
2173        temp_evt_len--;
2174      }
2175      rem_name.remote_bd_name[rem_name.length] = 0;
2176    }
2177
2178    /* If processing a stand alone remote name then report the error in the
2179       callback */
2180    else {
2181      rem_name.status = BTM_BAD_VALUE_RET;
2182      rem_name.length = 0;
2183      rem_name.remote_bd_name[0] = 0;
2184    }
2185    /* Reset the remote BAD to zero and call callback if possible */
2186    memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2187
2188    p_inq->p_remname_cmpl_cb = NULL;
2189    if (p_cb) (p_cb)((tBTM_REMOTE_DEV_NAME*)&rem_name);
2190  }
2191}
2192
2193void btm_inq_remote_name_timer_timeout(UNUSED_ATTR void* data) {
2194  btm_inq_rmt_name_failed();
2195}
2196
2197/*******************************************************************************
2198 *
2199 * Function         btm_inq_rmt_name_failed
2200 *
2201 * Description      This function is if timeout expires while getting remote
2202 *                  name.  This is done for devices that incorrectly do not
2203 *                  report operation failure
2204 *
2205 * Returns          void
2206 *
2207 ******************************************************************************/
2208void btm_inq_rmt_name_failed(void) {
2209  BTM_TRACE_ERROR("btm_inq_rmt_name_failed()  remname_active=%d",
2210                  btm_cb.btm_inq_vars.remname_active);
2211
2212  if (btm_cb.btm_inq_vars.remname_active)
2213    btm_process_remote_name(btm_cb.btm_inq_vars.remname_bda, NULL, 0,
2214                            HCI_ERR_UNSPECIFIED);
2215  else
2216    btm_process_remote_name(NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2217
2218  btm_sec_rmt_name_request_complete(NULL, NULL, HCI_ERR_UNSPECIFIED);
2219}
2220
2221/*******************************************************************************
2222 *
2223 * Function         btm_read_inq_tx_power_timeout
2224 *
2225 * Description      Callback when reading the inquiry tx power times out.
2226 *
2227 * Returns          void
2228 *
2229 ******************************************************************************/
2230void btm_read_inq_tx_power_timeout(UNUSED_ATTR void* data) {
2231  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_inq_tx_power_cmpl_cb;
2232  btm_cb.devcb.p_inq_tx_power_cmpl_cb = NULL;
2233  if (p_cb) (*p_cb)((void*)NULL);
2234}
2235
2236/*******************************************************************************
2237 *
2238 * Function         btm_read_inq_tx_power_complete
2239 *
2240 * Description      read inquiry tx power level complete callback function.
2241 *
2242 * Returns          void
2243 *
2244 ******************************************************************************/
2245void btm_read_inq_tx_power_complete(uint8_t* p) {
2246  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_inq_tx_power_cmpl_cb;
2247  tBTM_INQ_TXPWR_RESULTS results;
2248
2249  BTM_TRACE_DEBUG("%s", __func__);
2250  alarm_cancel(btm_cb.devcb.read_inq_tx_power_timer);
2251  btm_cb.devcb.p_inq_tx_power_cmpl_cb = NULL;
2252
2253  /* If there was a registered callback, call it */
2254  if (p_cb) {
2255    STREAM_TO_UINT8(results.hci_status, p);
2256
2257    if (results.hci_status == HCI_SUCCESS) {
2258      results.status = BTM_SUCCESS;
2259
2260      STREAM_TO_UINT8(results.tx_power, p);
2261      BTM_TRACE_EVENT(
2262          "BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x",
2263          results.tx_power, results.hci_status);
2264    } else
2265      results.status = BTM_ERR_PROCESSING;
2266
2267    (*p_cb)(&results);
2268  }
2269}
2270/*******************************************************************************
2271 *
2272 * Function         BTM_WriteEIR
2273 *
2274 * Description      This function is called to write EIR data to controller.
2275 *
2276 * Parameters       p_buff - allocated HCI command buffer including extended
2277 *                           inquriry response
2278 *
2279 * Returns          BTM_SUCCESS  - if successful
2280 *                  BTM_MODE_UNSUPPORTED - if local device cannot support it
2281 *
2282 ******************************************************************************/
2283tBTM_STATUS BTM_WriteEIR(BT_HDR* p_buff) {
2284  if (controller_get_interface()->supports_extended_inquiry_response()) {
2285    BTM_TRACE_API("Write Extended Inquiry Response to controller");
2286    btsnd_hcic_write_ext_inquiry_response(p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2287    return BTM_SUCCESS;
2288  } else {
2289    osi_free(p_buff);
2290    return BTM_MODE_UNSUPPORTED;
2291  }
2292}
2293
2294/*******************************************************************************
2295 *
2296 * Function         btm_convert_uuid_to_eir_service
2297 *
2298 * Description      This function is called to get the bit position of UUID.
2299 *
2300 * Parameters       uuid16 - UUID 16-bit
2301 *
2302 * Returns          BTM EIR service ID if found
2303 *                  BTM_EIR_MAX_SERVICES - if not found
2304 *
2305 ******************************************************************************/
2306static uint8_t btm_convert_uuid_to_eir_service(uint16_t uuid16) {
2307  uint8_t xx;
2308
2309  for (xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++) {
2310    if (uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
2311      return xx;
2312    }
2313  }
2314  return BTM_EIR_MAX_SERVICES;
2315}
2316
2317/*******************************************************************************
2318 *
2319 * Function         BTM_HasEirService
2320 *
2321 * Description      This function is called to know if UUID in bit map of UUID.
2322 *
2323 * Parameters       p_eir_uuid - bit map of UUID list
2324 *                  uuid16 - UUID 16-bit
2325 *
2326 * Returns          true - if found
2327 *                  false - if not found
2328 *
2329 ******************************************************************************/
2330bool BTM_HasEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
2331  uint8_t service_id;
2332
2333  service_id = btm_convert_uuid_to_eir_service(uuid16);
2334  if (service_id < BTM_EIR_MAX_SERVICES)
2335    return (BTM_EIR_HAS_SERVICE(p_eir_uuid, service_id));
2336  else
2337    return (false);
2338}
2339
2340/*******************************************************************************
2341 *
2342 * Function         BTM_HasInquiryEirService
2343 *
2344 * Description      This function is called to know if UUID in bit map of UUID
2345 *                  list.
2346 *
2347 * Parameters       p_results - inquiry results
2348 *                  uuid16 - UUID 16-bit
2349 *
2350 * Returns          BTM_EIR_FOUND - if found
2351 *                  BTM_EIR_NOT_FOUND - if not found and it is complete list
2352 *                  BTM_EIR_UNKNOWN - if not found and it is not complete list
2353 *
2354 ******************************************************************************/
2355tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService(tBTM_INQ_RESULTS* p_results,
2356                                                uint16_t uuid16) {
2357  if (BTM_HasEirService(p_results->eir_uuid, uuid16)) {
2358    return BTM_EIR_FOUND;
2359  } else if (p_results->eir_complete_list) {
2360    return BTM_EIR_NOT_FOUND;
2361  } else
2362    return BTM_EIR_UNKNOWN;
2363}
2364
2365/*******************************************************************************
2366 *
2367 * Function         BTM_AddEirService
2368 *
2369 * Description      This function is called to add a service in bit map of UUID
2370 *                  list.
2371 *
2372 * Parameters       p_eir_uuid - bit mask of UUID list for EIR
2373 *                  uuid16 - UUID 16-bit
2374 *
2375 * Returns          None
2376 *
2377 ******************************************************************************/
2378void BTM_AddEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
2379  uint8_t service_id;
2380
2381  service_id = btm_convert_uuid_to_eir_service(uuid16);
2382  if (service_id < BTM_EIR_MAX_SERVICES)
2383    BTM_EIR_SET_SERVICE(p_eir_uuid, service_id);
2384}
2385
2386/*******************************************************************************
2387 *
2388 * Function         BTM_RemoveEirService
2389 *
2390 * Description      This function is called to remove a service in bit map of
2391 *                  UUID list.
2392 *
2393 * Parameters       p_eir_uuid - bit mask of UUID list for EIR
2394 *                  uuid16 - UUID 16-bit
2395 *
2396 * Returns          None
2397 *
2398 ******************************************************************************/
2399void BTM_RemoveEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
2400  uint8_t service_id;
2401
2402  service_id = btm_convert_uuid_to_eir_service(uuid16);
2403  if (service_id < BTM_EIR_MAX_SERVICES)
2404    BTM_EIR_CLR_SERVICE(p_eir_uuid, service_id);
2405}
2406
2407/*******************************************************************************
2408 *
2409 * Function         BTM_GetEirSupportedServices
2410 *
2411 * Description      This function is called to get UUID list from bit map of
2412 *                  UUID list.
2413 *
2414 * Parameters       p_eir_uuid - bit mask of UUID list for EIR
2415 *                  p - reference of current pointer of EIR
2416 *                  max_num_uuid16 - max number of UUID can be written in EIR
2417 *                  num_uuid16 - number of UUID have been written in EIR
2418 *
2419 * Returns          BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2420 *                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2421 *
2422 ******************************************************************************/
2423uint8_t BTM_GetEirSupportedServices(uint32_t* p_eir_uuid, uint8_t** p,
2424                                    uint8_t max_num_uuid16,
2425                                    uint8_t* p_num_uuid16) {
2426  uint8_t service_index;
2427
2428  *p_num_uuid16 = 0;
2429
2430  for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES;
2431       service_index++) {
2432    if (BTM_EIR_HAS_SERVICE(p_eir_uuid, service_index)) {
2433      if (*p_num_uuid16 < max_num_uuid16) {
2434        UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2435        (*p_num_uuid16)++;
2436      }
2437      /* if max number of UUIDs are stored and found one more */
2438      else {
2439        return BTM_EIR_MORE_16BITS_UUID_TYPE;
2440      }
2441    }
2442  }
2443  return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2444}
2445
2446/*******************************************************************************
2447 *
2448 * Function         BTM_GetEirUuidList
2449 *
2450 * Description      This function parses EIR and returns UUID list.
2451 *
2452 * Parameters       p_eir - EIR
2453 *                  eir_len - EIR len
2454 *                  uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2455 *                  p_num_uuid - return number of UUID in found list
2456 *                  p_uuid_list - return UUID list
2457 *                  max_num_uuid - maximum number of UUID to be returned
2458 *
2459 * Returns          0 - if not found
2460 *                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2461 *                  BTM_EIR_MORE_16BITS_UUID_TYPE
2462 *                  BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2463 *                  BTM_EIR_MORE_32BITS_UUID_TYPE
2464 *                  BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2465 *                  BTM_EIR_MORE_128BITS_UUID_TYPE
2466 *
2467 ******************************************************************************/
2468uint8_t BTM_GetEirUuidList(uint8_t* p_eir, size_t eir_len, uint8_t uuid_size,
2469                           uint8_t* p_num_uuid, uint8_t* p_uuid_list,
2470                           uint8_t max_num_uuid) {
2471  const uint8_t* p_uuid_data;
2472  uint8_t type;
2473  uint8_t yy, xx;
2474  uint16_t* p_uuid16 = (uint16_t*)p_uuid_list;
2475  uint32_t* p_uuid32 = (uint32_t*)p_uuid_list;
2476  char buff[LEN_UUID_128 * 2 + 1];
2477
2478  p_uuid_data =
2479      btm_eir_get_uuid_list(p_eir, eir_len, uuid_size, p_num_uuid, &type);
2480  if (p_uuid_data == NULL) {
2481    return 0x00;
2482  }
2483
2484  if (*p_num_uuid > max_num_uuid) {
2485    BTM_TRACE_WARNING("%s: number of uuid in EIR = %d, size of uuid list = %d",
2486                      __func__, *p_num_uuid, max_num_uuid);
2487    *p_num_uuid = max_num_uuid;
2488  }
2489
2490  BTM_TRACE_DEBUG("%s: type = %02X, number of uuid = %d", __func__, type,
2491                  *p_num_uuid);
2492
2493  if (uuid_size == LEN_UUID_16) {
2494    for (yy = 0; yy < *p_num_uuid; yy++) {
2495      STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2496      BTM_TRACE_DEBUG("                     0x%04X", *(p_uuid16 + yy));
2497    }
2498  } else if (uuid_size == LEN_UUID_32) {
2499    for (yy = 0; yy < *p_num_uuid; yy++) {
2500      STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2501      BTM_TRACE_DEBUG("                     0x%08X", *(p_uuid32 + yy));
2502    }
2503  } else if (uuid_size == LEN_UUID_128) {
2504    for (yy = 0; yy < *p_num_uuid; yy++) {
2505      STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2506      for (xx = 0; xx < LEN_UUID_128; xx++)
2507        snprintf(buff + xx * 2, sizeof(buff) - xx * 2, "%02X",
2508                 *(p_uuid_list + yy * LEN_UUID_128 + xx));
2509      BTM_TRACE_DEBUG("                     0x%s", buff);
2510    }
2511  }
2512
2513  return type;
2514}
2515
2516/*******************************************************************************
2517 *
2518 * Function         btm_eir_get_uuid_list
2519 *
2520 * Description      This function searches UUID list in EIR.
2521 *
2522 * Parameters       p_eir - address of EIR
2523 *                  eir_len - EIR length
2524 *                  uuid_size - size of UUID to find
2525 *                  p_num_uuid - number of UUIDs found
2526 *                  p_uuid_list_type - EIR data type
2527 *
2528 * Returns          NULL - if UUID list with uuid_size is not found
2529 *                  beginning of UUID list in EIR - otherwise
2530 *
2531 ******************************************************************************/
2532static const uint8_t* btm_eir_get_uuid_list(uint8_t* p_eir, size_t eir_len,
2533                                            uint8_t uuid_size,
2534                                            uint8_t* p_num_uuid,
2535                                            uint8_t* p_uuid_list_type) {
2536  const uint8_t* p_uuid_data;
2537  uint8_t complete_type, more_type;
2538  uint8_t uuid_len;
2539
2540  switch (uuid_size) {
2541    case LEN_UUID_16:
2542      complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2543      more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2544      break;
2545    case LEN_UUID_32:
2546      complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2547      more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
2548      break;
2549    case LEN_UUID_128:
2550      complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2551      more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
2552      break;
2553    default:
2554      *p_num_uuid = 0;
2555      return NULL;
2556      break;
2557  }
2558
2559  p_uuid_data = AdvertiseDataParser::GetFieldByType(p_eir, eir_len,
2560                                                    complete_type, &uuid_len);
2561  if (p_uuid_data == NULL) {
2562    p_uuid_data = AdvertiseDataParser::GetFieldByType(p_eir, eir_len, more_type,
2563                                                      &uuid_len);
2564    *p_uuid_list_type = more_type;
2565  } else {
2566    *p_uuid_list_type = complete_type;
2567  }
2568
2569  *p_num_uuid = uuid_len / uuid_size;
2570  return p_uuid_data;
2571}
2572
2573/*******************************************************************************
2574 *
2575 * Function         btm_convert_uuid_to_uuid16
2576 *
2577 * Description      This function converts UUID to UUID 16-bit.
2578 *
2579 * Parameters       p_uuid - address of UUID
2580 *                  uuid_size - size of UUID
2581 *
2582 * Returns          0 - if UUID cannot be converted to UUID 16-bit
2583 *                  UUID 16-bit - otherwise
2584 *
2585 ******************************************************************************/
2586static uint16_t btm_convert_uuid_to_uuid16(const uint8_t* p_uuid,
2587                                           uint8_t uuid_size) {
2588  static const uint8_t base_uuid[LEN_UUID_128] = {
2589      0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2590      0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2591  uint16_t uuid16 = 0;
2592  uint32_t uuid32;
2593  bool is_base_uuid;
2594  uint8_t xx;
2595
2596  switch (uuid_size) {
2597    case LEN_UUID_16:
2598      STREAM_TO_UINT16(uuid16, p_uuid);
2599      break;
2600    case LEN_UUID_32:
2601      STREAM_TO_UINT32(uuid32, p_uuid);
2602      if (uuid32 < 0x10000) uuid16 = (uint16_t)uuid32;
2603      break;
2604    case LEN_UUID_128:
2605      /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2606      is_base_uuid = true;
2607      for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
2608        if (p_uuid[xx] != base_uuid[xx]) {
2609          is_base_uuid = false;
2610          break;
2611        }
2612      }
2613      if (is_base_uuid) {
2614        if ((p_uuid[LEN_UUID_128 - 1] == 0) &&
2615            (p_uuid[LEN_UUID_128 - 2] == 0)) {
2616          p_uuid += (LEN_UUID_128 - 4);
2617          STREAM_TO_UINT16(uuid16, p_uuid);
2618        }
2619      }
2620      break;
2621    default:
2622      BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size");
2623      break;
2624  }
2625
2626  return (uuid16);
2627}
2628
2629/*******************************************************************************
2630 *
2631 * Function         btm_set_eir_uuid
2632 *
2633 * Description      This function is called to store received UUID into inquiry
2634 *                  result.
2635 *
2636 * Parameters       p_eir - pointer of EIR significant part
2637 *                  p_results - pointer of inquiry result
2638 *
2639 * Returns          None
2640 *
2641 ******************************************************************************/
2642void btm_set_eir_uuid(uint8_t* p_eir, tBTM_INQ_RESULTS* p_results) {
2643  const uint8_t* p_uuid_data;
2644  uint8_t num_uuid;
2645  uint16_t uuid16;
2646  uint8_t yy;
2647  uint8_t type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2648
2649  p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
2650                                      LEN_UUID_16, &num_uuid, &type);
2651
2652  if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
2653    p_results->eir_complete_list = true;
2654  } else {
2655    p_results->eir_complete_list = false;
2656  }
2657
2658  BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X",
2659                p_results->eir_complete_list);
2660
2661  if (p_uuid_data) {
2662    for (yy = 0; yy < num_uuid; yy++) {
2663      STREAM_TO_UINT16(uuid16, p_uuid_data);
2664      BTM_AddEirService(p_results->eir_uuid, uuid16);
2665    }
2666  }
2667
2668  p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
2669                                      LEN_UUID_32, &num_uuid, &type);
2670  if (p_uuid_data) {
2671    for (yy = 0; yy < num_uuid; yy++) {
2672      uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, LEN_UUID_32);
2673      p_uuid_data += LEN_UUID_32;
2674      if (uuid16) BTM_AddEirService(p_results->eir_uuid, uuid16);
2675    }
2676  }
2677
2678  p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
2679                                      LEN_UUID_128, &num_uuid, &type);
2680  if (p_uuid_data) {
2681    for (yy = 0; yy < num_uuid; yy++) {
2682      uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, LEN_UUID_128);
2683      p_uuid_data += LEN_UUID_128;
2684      if (uuid16) BTM_AddEirService(p_results->eir_uuid, uuid16);
2685    }
2686  }
2687}
2688