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