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 
54 extern 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 /******************************************************************************/
59 static const LAP general_inq_lap = {0x9e, 0x8b, 0x33};
60 static const LAP limited_inq_lap = {0x9e, 0x8b, 0x00};
61 
62 const 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 /******************************************************************************/
115 static void btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST* p_inq);
116 static tBTM_STATUS btm_set_inq_event_filter(uint8_t filter_cond_type,
117                                             tBTM_INQ_FILT_COND* p_filt_cond);
118 static void btm_clr_inq_result_flt(void);
119 
120 static uint8_t btm_convert_uuid_to_eir_service(uint16_t uuid16);
121 static void btm_set_eir_uuid(uint8_t* p_eir, tBTM_INQ_RESULTS* p_results);
122 static 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);
126 static 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  ******************************************************************************/
BTM_SetDiscoverability(uint16_t inq_mode,uint16_t window,uint16_t interval)145 tBTM_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  ******************************************************************************/
BTM_SetInquiryScanType(uint16_t scan_type)256 tBTM_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  ******************************************************************************/
BTM_SetPageScanType(uint16_t scan_type)289 tBTM_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  ******************************************************************************/
BTM_SetInquiryMode(uint8_t mode)325 tBTM_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  ******************************************************************************/
BTM_ReadDiscoverability(uint16_t * p_window,uint16_t * p_interval)360 uint16_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  ******************************************************************************/
BTM_SetPeriodicInquiryMode(tBTM_INQ_PARMS * p_inqparms,uint16_t max_delay,uint16_t min_delay,tBTM_INQ_RESULTS_CB * p_results_cb)407 tBTM_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  ******************************************************************************/
BTM_CancelPeriodicInquiry(void)496 tBTM_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  ******************************************************************************/
BTM_SetConnectability(uint16_t page_mode,uint16_t window,uint16_t interval)537 tBTM_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  ******************************************************************************/
BTM_ReadConnectability(uint16_t * p_window,uint16_t * p_interval)612 uint16_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  ******************************************************************************/
BTM_IsInquiryActive(void)634 uint16_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  ******************************************************************************/
BTM_CancelInquiry(void)651 tBTM_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  ******************************************************************************/
BTM_StartInquiry(tBTM_INQ_PARMS * p_inqparms,tBTM_INQ_RESULTS_CB * p_results_cb,tBTM_CMPL_CB * p_cmpl_cb)746 tBTM_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  ******************************************************************************/
BTM_ReadRemoteDeviceName(BD_ADDR remote_bda,tBTM_CMPL_CB * p_cb,tBT_TRANSPORT transport)957 tBTM_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  ******************************************************************************/
BTM_CancelRemoteDeviceName(void)989 tBTM_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  ******************************************************************************/
BTM_InqDbRead(const BD_ADDR p_bda)1020 tBTM_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  ******************************************************************************/
BTM_InqDbFirst(void)1043 tBTM_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  ******************************************************************************/
BTM_InqDbNext(tBTM_INQ_INFO * p_cur)1066 tBTM_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  ******************************************************************************/
BTM_ClearInqDb(BD_ADDR p_bda)1099 tBTM_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  ******************************************************************************/
BTM_ReadInquiryRspTxPower(tBTM_CMPL_CB * p_cb)1122 tBTM_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  ******************************************************************************/
btm_inq_db_reset(void)1151 void 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  ******************************************************************************/
btm_inq_db_init(void)1227 void 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  ******************************************************************************/
btm_inq_stop_on_ssp(void)1243 void 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  ******************************************************************************/
btm_inq_clear_ssp(void)1278 void 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  ******************************************************************************/
btm_clr_inq_db(BD_ADDR p_bda)1295 void 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  ******************************************************************************/
btm_clr_inq_result_flt(void)1329 static 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  ******************************************************************************/
btm_inq_find_bdaddr(BD_ADDR p_bda)1347 bool 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  ******************************************************************************/
btm_inq_db_find(const BD_ADDR p_bda)1382 tINQ_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  ******************************************************************************/
btm_inq_db_new(BD_ADDR p_bda)1407 tINQ_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  ******************************************************************************/
btm_set_inq_event_filter(uint8_t filter_cond_type,tBTM_INQ_FILT_COND * p_filt_cond)1462 static 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  ******************************************************************************/
btm_event_filter_complete(uint8_t * p)1525 void 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  ******************************************************************************/
btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST * p_inq)1636 static 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  ******************************************************************************/
btm_process_inq_results(uint8_t * p,uint8_t inq_res_mode)1693 void 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  ******************************************************************************/
btm_sort_inq_result(void)1890 void 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  ******************************************************************************/
btm_process_inq_complete(uint8_t status,uint8_t mode)1930 void 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  ******************************************************************************/
btm_process_cancel_complete(uint8_t status,uint8_t mode)2040 void 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  ******************************************************************************/
btm_initiate_rem_name(BD_ADDR remote_bda,uint8_t origin,period_ms_t timeout_ms,tBTM_CMPL_CB * p_cb)2065 tBTM_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  ******************************************************************************/
btm_process_remote_name(BD_ADDR bda,BD_NAME bdn,uint16_t evt_len,uint8_t hci_status)2125 void 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 
btm_inq_remote_name_timer_timeout(UNUSED_ATTR void * data)2193 void 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  ******************************************************************************/
btm_inq_rmt_name_failed(void)2208 void 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  ******************************************************************************/
btm_read_inq_tx_power_timeout(UNUSED_ATTR void * data)2230 void 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  ******************************************************************************/
btm_read_inq_tx_power_complete(uint8_t * p)2245 void 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  ******************************************************************************/
BTM_WriteEIR(BT_HDR * p_buff)2283 tBTM_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  ******************************************************************************/
btm_convert_uuid_to_eir_service(uint16_t uuid16)2306 static 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  ******************************************************************************/
BTM_HasEirService(uint32_t * p_eir_uuid,uint16_t uuid16)2330 bool 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  ******************************************************************************/
BTM_HasInquiryEirService(tBTM_INQ_RESULTS * p_results,uint16_t uuid16)2355 tBTM_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  ******************************************************************************/
BTM_AddEirService(uint32_t * p_eir_uuid,uint16_t uuid16)2378 void 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  ******************************************************************************/
BTM_RemoveEirService(uint32_t * p_eir_uuid,uint16_t uuid16)2399 void 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  ******************************************************************************/
BTM_GetEirSupportedServices(uint32_t * p_eir_uuid,uint8_t ** p,uint8_t max_num_uuid16,uint8_t * p_num_uuid16)2423 uint8_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  ******************************************************************************/
BTM_GetEirUuidList(uint8_t * p_eir,size_t eir_len,uint8_t uuid_size,uint8_t * p_num_uuid,uint8_t * p_uuid_list,uint8_t max_num_uuid)2468 uint8_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  ******************************************************************************/
btm_eir_get_uuid_list(uint8_t * p_eir,size_t eir_len,uint8_t uuid_size,uint8_t * p_num_uuid,uint8_t * p_uuid_list_type)2532 static 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  ******************************************************************************/
btm_convert_uuid_to_uuid16(const uint8_t * p_uuid,uint8_t uuid_size)2586 static 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  ******************************************************************************/
btm_set_eir_uuid(uint8_t * p_eir,tBTM_INQ_RESULTS * p_results)2642 void 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