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
SendRemoteNameRequest(const RawAddress & raw_address)130 void SendRemoteNameRequest(const RawAddress& raw_address) {
131 if (bluetooth::shim::is_gd_shim_enabled()) {
132 return bluetooth::shim::SendRemoteNameRequest(raw_address);
133 } else {
134 btsnd_hcic_rmt_name_req(raw_address, HCI_PAGE_SCAN_REP_MODE_R1,
135 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
136 }
137 }
138 /*******************************************************************************
139 *
140 * Function BTM_SetDiscoverability
141 *
142 * Description This function is called to set the device into or out of
143 * discoverable mode. Discoverable mode means inquiry
144 * scans are enabled. If a value of '0' is entered for window
145 * or interval, the default values are used.
146 *
147 * Returns BTM_SUCCESS if successful
148 * BTM_BUSY if a setting of the filter is already in progress
149 * BTM_NO_RESOURCES if couldn't get a memory pool buffer
150 * BTM_ILLEGAL_VALUE if a bad parameter was detected
151 * BTM_WRONG_MODE if the device is not up.
152 *
153 ******************************************************************************/
BTM_SetDiscoverability(uint16_t inq_mode,uint16_t window,uint16_t interval)154 tBTM_STATUS BTM_SetDiscoverability(uint16_t inq_mode, uint16_t window,
155 uint16_t interval) {
156 if (bluetooth::shim::is_gd_shim_enabled()) {
157 return bluetooth::shim::BTM_SetDiscoverability(inq_mode, window, interval);
158 }
159
160 uint8_t scan_mode = 0;
161 uint16_t service_class;
162 uint8_t* p_cod;
163 uint8_t major, minor;
164 DEV_CLASS cod;
165 LAP temp_lap[2];
166 bool is_limited;
167 bool cod_limited;
168
169 BTM_TRACE_API("BTM_SetDiscoverability");
170 if (controller_get_interface()->supports_ble()) {
171 if (btm_ble_set_discoverability((uint16_t)(inq_mode)) == BTM_SUCCESS) {
172 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
173 btm_cb.btm_inq_vars.discoverable_mode |=
174 (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
175 }
176 }
177 inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
178
179 /*** Check mode parameter ***/
180 if (inq_mode > BTM_MAX_DISCOVERABLE) return (BTM_ILLEGAL_VALUE);
181
182 /* Make sure the controller is active */
183 if (!controller_get_interface()->get_is_ready()) return (BTM_DEV_RESET);
184
185 /* If the window and/or interval is '0', set to default values */
186 if (!window) window = BTM_DEFAULT_DISC_WINDOW;
187
188 if (!interval) interval = BTM_DEFAULT_DISC_INTERVAL;
189
190 BTM_TRACE_API(
191 "BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window "
192 "0x%04x, interval 0x%04x",
193 inq_mode, window, interval);
194
195 /*** Check for valid window and interval parameters ***/
196 /*** Only check window and duration if mode is connectable ***/
197 if (inq_mode != BTM_NON_DISCOVERABLE) {
198 /* window must be less than or equal to interval */
199 if (window < HCI_MIN_INQUIRYSCAN_WINDOW ||
200 window > HCI_MAX_INQUIRYSCAN_WINDOW ||
201 interval < HCI_MIN_INQUIRYSCAN_INTERVAL ||
202 interval > HCI_MAX_INQUIRYSCAN_INTERVAL || window > interval) {
203 return (BTM_ILLEGAL_VALUE);
204 }
205 }
206
207 /* Set the IAC if needed */
208 if (inq_mode != BTM_NON_DISCOVERABLE) {
209 if (inq_mode & BTM_LIMITED_DISCOVERABLE) {
210 /* Use the GIAC and LIAC codes for limited discoverable mode */
211 memcpy(temp_lap[0], limited_inq_lap, LAP_LEN);
212 memcpy(temp_lap[1], general_inq_lap, LAP_LEN);
213
214 btsnd_hcic_write_cur_iac_lap(2, (LAP * const)temp_lap);
215 } else {
216 btsnd_hcic_write_cur_iac_lap(1, (LAP * const) & general_inq_lap);
217 }
218
219 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
220 }
221
222 /* Send down the inquiry scan window and period if changed */
223 if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
224 (interval != btm_cb.btm_inq_vars.inq_scan_period)) {
225 btsnd_hcic_write_inqscan_cfg(interval, window);
226 btm_cb.btm_inq_vars.inq_scan_window = window;
227 btm_cb.btm_inq_vars.inq_scan_period = interval;
228 }
229
230 if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK)
231 scan_mode |= HCI_PAGE_SCAN_ENABLED;
232
233 btsnd_hcic_write_scan_enable(scan_mode);
234 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
235 btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
236
237 /* Change the service class bit if mode has changed */
238 p_cod = BTM_ReadDeviceClass();
239 BTM_COD_SERVICE_CLASS(service_class, p_cod);
240 is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? true : false;
241 cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false;
242 if (is_limited ^ cod_limited) {
243 BTM_COD_MINOR_CLASS(minor, p_cod);
244 BTM_COD_MAJOR_CLASS(major, p_cod);
245 if (is_limited)
246 service_class |= BTM_COD_SERVICE_LMTD_DISCOVER;
247 else
248 service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER;
249
250 FIELDS_TO_COD(cod, minor, major, service_class);
251 (void)BTM_SetDeviceClass(cod);
252 }
253
254 return (BTM_SUCCESS);
255 }
256
257 /*******************************************************************************
258 *
259 * Function BTM_SetInquiryScanType
260 *
261 * Description This function is called to set the iquiry scan-type to
262 * standard or interlaced.
263 *
264 * Returns BTM_SUCCESS if successful
265 * BTM_MODE_UNSUPPORTED if not a 1.2 device
266 * BTM_WRONG_MODE if the device is not up.
267 *
268 ******************************************************************************/
BTM_SetInquiryScanType(uint16_t scan_type)269 tBTM_STATUS BTM_SetInquiryScanType(uint16_t scan_type) {
270 if (bluetooth::shim::is_gd_shim_enabled()) {
271 return bluetooth::shim::BTM_SetInquiryScanType(scan_type);
272 }
273
274 BTM_TRACE_API("BTM_SetInquiryScanType");
275 if (scan_type != BTM_SCAN_TYPE_STANDARD &&
276 scan_type != BTM_SCAN_TYPE_INTERLACED)
277 return (BTM_ILLEGAL_VALUE);
278
279 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
280 if (!controller_get_interface()->supports_interlaced_inquiry_scan())
281 return (BTM_MODE_UNSUPPORTED);
282
283 /* Check for scan type if configuration has been changed */
284 if (scan_type != btm_cb.btm_inq_vars.inq_scan_type) {
285 if (BTM_IsDeviceUp()) {
286 btsnd_hcic_write_inqscan_type((uint8_t)scan_type);
287 btm_cb.btm_inq_vars.inq_scan_type = scan_type;
288 } else
289 return (BTM_WRONG_MODE);
290 }
291 return (BTM_SUCCESS);
292 }
293
294 /*******************************************************************************
295 *
296 * Function BTM_SetPageScanType
297 *
298 * Description This function is called to set the page scan-type to
299 * standard or interlaced.
300 *
301 * Returns BTM_SUCCESS if successful
302 * BTM_MODE_UNSUPPORTED if not a 1.2 device
303 * BTM_WRONG_MODE if the device is not up.
304 *
305 ******************************************************************************/
BTM_SetPageScanType(uint16_t scan_type)306 tBTM_STATUS BTM_SetPageScanType(uint16_t scan_type) {
307 if (bluetooth::shim::is_gd_shim_enabled()) {
308 return bluetooth::shim::BTM_SetPageScanType(scan_type);
309 }
310
311 BTM_TRACE_API("BTM_SetPageScanType");
312 if (scan_type != BTM_SCAN_TYPE_STANDARD &&
313 scan_type != BTM_SCAN_TYPE_INTERLACED)
314 return (BTM_ILLEGAL_VALUE);
315
316 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
317 if (!controller_get_interface()->supports_interlaced_inquiry_scan())
318 return (BTM_MODE_UNSUPPORTED);
319
320 /* Check for scan type if configuration has been changed */
321 if (scan_type != btm_cb.btm_inq_vars.page_scan_type) {
322 if (BTM_IsDeviceUp()) {
323 btsnd_hcic_write_pagescan_type((uint8_t)scan_type);
324 btm_cb.btm_inq_vars.page_scan_type = scan_type;
325 } else
326 return (BTM_WRONG_MODE);
327 }
328 return (BTM_SUCCESS);
329 }
330
331 /*******************************************************************************
332 *
333 * Function BTM_SetInquiryMode
334 *
335 * Description This function is called to set standard or with RSSI
336 * mode of the inquiry for local device.
337 *
338 * Output Params: mode - standard, with RSSI, extended
339 *
340 * Returns BTM_SUCCESS if successful
341 * BTM_NO_RESOURCES if couldn't get a memory pool buffer
342 * BTM_ILLEGAL_VALUE if a bad parameter was detected
343 * BTM_WRONG_MODE if the device is not up.
344 *
345 ******************************************************************************/
BTM_SetInquiryMode(uint8_t mode)346 tBTM_STATUS BTM_SetInquiryMode(uint8_t mode) {
347 if (bluetooth::shim::is_gd_shim_enabled()) {
348 return bluetooth::shim::BTM_SetInquiryMode(mode);
349 }
350
351 const controller_t* controller = controller_get_interface();
352 BTM_TRACE_API("BTM_SetInquiryMode");
353 if (mode == BTM_INQ_RESULT_STANDARD) {
354 /* mandatory mode */
355 } else if (mode == BTM_INQ_RESULT_WITH_RSSI) {
356 if (!controller->supports_rssi_with_inquiry_results())
357 return (BTM_MODE_UNSUPPORTED);
358 } else if (mode == BTM_INQ_RESULT_EXTENDED) {
359 if (!controller->supports_extended_inquiry_response())
360 return (BTM_MODE_UNSUPPORTED);
361 } else
362 return (BTM_ILLEGAL_VALUE);
363
364 if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
365
366 btsnd_hcic_write_inquiry_mode(mode);
367
368 return (BTM_SUCCESS);
369 }
370
371 /*******************************************************************************
372 *
373 * Function BTM_ReadDiscoverability
374 *
375 * Description This function is called to read the current discoverability
376 * mode of the device.
377 *
378 * Output Params: p_window - current inquiry scan duration
379 * p_interval - current inquiry scan interval
380 *
381 * Returns BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
382 * BTM_GENERAL_DISCOVERABLE
383 *
384 ******************************************************************************/
BTM_ReadDiscoverability(uint16_t * p_window,uint16_t * p_interval)385 uint16_t BTM_ReadDiscoverability(uint16_t* p_window, uint16_t* p_interval) {
386 if (bluetooth::shim::is_gd_shim_enabled()) {
387 return bluetooth::shim::BTM_ReadDiscoverability(p_window, p_interval);
388 }
389
390 BTM_TRACE_API("BTM_ReadDiscoverability");
391 if (p_window) *p_window = btm_cb.btm_inq_vars.inq_scan_window;
392
393 if (p_interval) *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
394
395 return (btm_cb.btm_inq_vars.discoverable_mode);
396 }
397
398 /*******************************************************************************
399 *
400 * Function BTM_CancelPeriodicInquiry
401 *
402 * Description This function cancels a periodic inquiry
403 *
404 * Returns
405 * BTM_NO_RESOURCES if could not allocate a message buffer
406 * BTM_SUCCESS - if cancelling the periodic inquiry
407 * BTM_WRONG_MODE if the device is not up.
408 *
409 ******************************************************************************/
BTM_CancelPeriodicInquiry(void)410 tBTM_STATUS BTM_CancelPeriodicInquiry(void) {
411 if (bluetooth::shim::is_gd_shim_enabled()) {
412 return bluetooth::shim::BTM_CancelPeriodicInquiry();
413 }
414
415 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
416 tBTM_STATUS status = BTM_SUCCESS;
417 BTM_TRACE_API("BTM_CancelPeriodicInquiry called");
418
419 /*** Make sure the device is ready ***/
420 if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
421
422 /* Only cancel if one is active */
423 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
424 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
425 btm_cb.btm_inq_vars.p_inq_results_cb = NULL;
426
427 btsnd_hcic_exit_per_inq();
428
429 /* If the event filter is in progress, mark it so that the processing of the
430 return
431 event will be ignored */
432 if (p_inq->inqfilt_active) p_inq->pending_filt_complete_event++;
433
434 p_inq->inqfilt_active = false;
435 p_inq->inq_counter++;
436 }
437
438 return (status);
439 }
440
441 /*******************************************************************************
442 *
443 * Function BTM_SetConnectability
444 *
445 * Description This function is called to set the device into or out of
446 * connectable mode. Discoverable mode means page scans are
447 * enabled.
448 *
449 * Returns BTM_SUCCESS if successful
450 * BTM_ILLEGAL_VALUE if a bad parameter is detected
451 * BTM_NO_RESOURCES if could not allocate a message buffer
452 * BTM_WRONG_MODE if the device is not up.
453 *
454 ******************************************************************************/
BTM_SetConnectability(uint16_t page_mode,uint16_t window,uint16_t interval)455 tBTM_STATUS BTM_SetConnectability(uint16_t page_mode, uint16_t window,
456 uint16_t interval) {
457 if (bluetooth::shim::is_gd_shim_enabled()) {
458 return bluetooth::shim::BTM_SetConnectability(page_mode, window, interval);
459 }
460
461 uint8_t scan_mode = 0;
462 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
463
464 BTM_TRACE_API("BTM_SetConnectability");
465
466 if (controller_get_interface()->supports_ble()) {
467 if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS) {
468 return BTM_NO_RESOURCES;
469 }
470 p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
471 p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
472 }
473 page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
474
475 /*** Check mode parameter ***/
476 if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE)
477 return (BTM_ILLEGAL_VALUE);
478
479 /* Make sure the controller is active */
480 if (!controller_get_interface()->get_is_ready()) return (BTM_DEV_RESET);
481
482 /* If the window and/or interval is '0', set to default values */
483 if (!window) window = BTM_DEFAULT_CONN_WINDOW;
484
485 if (!interval) interval = BTM_DEFAULT_CONN_INTERVAL;
486
487 BTM_TRACE_API(
488 "BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, "
489 "interval 0x%04x",
490 page_mode, window, interval);
491
492 /*** Check for valid window and interval parameters ***/
493 /*** Only check window and duration if mode is connectable ***/
494 if (page_mode == BTM_CONNECTABLE) {
495 /* window must be less than or equal to interval */
496 if (window < HCI_MIN_PAGESCAN_WINDOW || window > HCI_MAX_PAGESCAN_WINDOW ||
497 interval < HCI_MIN_PAGESCAN_INTERVAL ||
498 interval > HCI_MAX_PAGESCAN_INTERVAL || window > interval) {
499 return (BTM_ILLEGAL_VALUE);
500 }
501
502 scan_mode |= HCI_PAGE_SCAN_ENABLED;
503 }
504
505 if ((window != p_inq->page_scan_window) ||
506 (interval != p_inq->page_scan_period)) {
507 p_inq->page_scan_window = window;
508 p_inq->page_scan_period = interval;
509 btsnd_hcic_write_pagescan_cfg(interval, window);
510 }
511
512 /* Keep the inquiry scan as previouosly set */
513 if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK)
514 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
515
516 btsnd_hcic_write_scan_enable(scan_mode);
517 p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
518 p_inq->connectable_mode |= page_mode;
519 return (BTM_SUCCESS);
520 }
521
522 /*******************************************************************************
523 *
524 * Function BTM_ReadConnectability
525 *
526 * Description This function is called to read the current discoverability
527 * mode of the device.
528 * Output Params p_window - current page scan duration
529 * p_interval - current time between page scans
530 *
531 * Returns BTM_NON_CONNECTABLE or BTM_CONNECTABLE
532 *
533 ******************************************************************************/
BTM_ReadConnectability(uint16_t * p_window,uint16_t * p_interval)534 uint16_t BTM_ReadConnectability(uint16_t* p_window, uint16_t* p_interval) {
535 if (bluetooth::shim::is_gd_shim_enabled()) {
536 return bluetooth::shim::BTM_ReadConnectability(p_window, p_interval);
537 }
538
539 BTM_TRACE_API("BTM_ReadConnectability");
540 if (p_window) *p_window = btm_cb.btm_inq_vars.page_scan_window;
541
542 if (p_interval) *p_interval = btm_cb.btm_inq_vars.page_scan_period;
543
544 return (btm_cb.btm_inq_vars.connectable_mode);
545 }
546
547 /*******************************************************************************
548 *
549 * Function BTM_IsInquiryActive
550 *
551 * Description This function returns a bit mask of the current inquiry
552 * state
553 *
554 * Returns BTM_INQUIRY_INACTIVE if inactive (0)
555 * BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active
556 * BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active
557 * BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active
558 *
559 ******************************************************************************/
BTM_IsInquiryActive(void)560 uint16_t BTM_IsInquiryActive(void) {
561 if (bluetooth::shim::is_gd_shim_enabled()) {
562 return bluetooth::shim::BTM_IsInquiryActive();
563 }
564
565 BTM_TRACE_API("BTM_IsInquiryActive");
566
567 return (btm_cb.btm_inq_vars.inq_active);
568 }
569
570 /*******************************************************************************
571 *
572 * Function BTM_CancelInquiry
573 *
574 * Description This function cancels an inquiry if active
575 *
576 * Returns BTM_SUCCESS if successful
577 * BTM_NO_RESOURCES if could not allocate a message buffer
578 * BTM_WRONG_MODE if the device is not up.
579 *
580 ******************************************************************************/
BTM_CancelInquiry(void)581 tBTM_STATUS BTM_CancelInquiry(void) {
582 if (bluetooth::shim::is_gd_shim_enabled()) {
583 return bluetooth::shim::BTM_CancelInquiry();
584 }
585
586 tBTM_STATUS status = BTM_SUCCESS;
587 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
588 BTM_TRACE_API("BTM_CancelInquiry called");
589
590 /*** Make sure the device is ready ***/
591 if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
592
593 /* Only cancel if not in periodic mode, otherwise the caller should call
594 * BTM_CancelPeriodicMode */
595 if ((p_inq->inq_active & BTM_INQUIRY_ACTIVE_MASK) != 0 &&
596 (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))) {
597 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
598 p_inq->state = BTM_INQ_INACTIVE_STATE;
599 p_inq->p_inq_results_cb = NULL; /* Do not notify caller anymore */
600 p_inq->p_inq_cmpl_cb = NULL; /* Do not notify caller anymore */
601
602 /* If the event filter is in progress, mark it so that the processing of the
603 return
604 event will be ignored */
605 if (p_inq->inqfilt_active) {
606 p_inq->inqfilt_active = false;
607 p_inq->pending_filt_complete_event++;
608 }
609 /* Initiate the cancel inquiry */
610 else {
611 if ((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0) {
612 btsnd_hcic_inq_cancel();
613 }
614 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
615 btm_ble_stop_inquiry();
616 }
617
618 /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
619 * and then send the BUSY_LEVEL event
620 * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
621 */
622
623 p_inq->inq_counter++;
624 btm_clr_inq_result_flt();
625 }
626
627 return (status);
628 }
629
630 /*******************************************************************************
631 *
632 * Function BTM_StartInquiry
633 *
634 * Description This function is called to start an inquiry.
635 *
636 * Parameters: p_inqparms - pointer to the inquiry information
637 * mode - GENERAL or LIMITED inquiry, BR/LE bit mask
638 * seperately
639 * duration - length in 1.28 sec intervals (If '0', the
640 * inquiry is CANCELLED)
641 * max_resps - maximum amount of devices to search for
642 * before ending the inquiry
643 * filter_cond_type - BTM_CLR_INQUIRY_FILTER,
644 * BTM_FILTER_COND_DEVICE_CLASS, or
645 * BTM_FILTER_COND_BD_ADDR
646 * filter_cond - value for the filter (based on
647 * filter_cond_type)
648 *
649 * p_results_cb - Pointer to the callback routine which gets
650 * called upon receipt of an inquiry result. If
651 * this field is NULL, the application is not
652 * notified.
653 *
654 * p_cmpl_cb - Pointer to the callback routine which gets
655 * called upon completion. If this field is
656 * NULL, the application is not notified when
657 * completed.
658 * Returns tBTM_STATUS
659 * BTM_CMD_STARTED if successfully initiated
660 * BTM_BUSY if already in progress
661 * BTM_ILLEGAL_VALUE if parameter(s) are out of range
662 * BTM_NO_RESOURCES if could not allocate resources to start
663 * the command
664 * BTM_WRONG_MODE if the device is not up.
665 *
666 ******************************************************************************/
BTM_StartInquiry(tBTM_INQ_PARMS * p_inqparms,tBTM_INQ_RESULTS_CB * p_results_cb,tBTM_CMPL_CB * p_cmpl_cb)667 tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
668 tBTM_INQ_RESULTS_CB* p_results_cb,
669 tBTM_CMPL_CB* p_cmpl_cb) {
670 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
671
672 if (bluetooth::shim::is_gd_shim_enabled()) {
673 return bluetooth::shim::BTM_StartInquiry(p_inqparms, p_results_cb,
674 p_cmpl_cb);
675 }
676
677 BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
678 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
679 p_inqparms->filter_cond_type);
680
681 /* Only one active inquiry is allowed in this implementation.
682 Also do not allow an inquiry if the inquiry filter is being updated */
683 if (p_inq->inq_active || p_inq->inqfilt_active) {
684 LOG(ERROR) << __func__ << ": BTM_BUSY";
685 return (BTM_BUSY);
686 } else {
687 p_inq->scan_type = INQ_GENERAL;
688 }
689
690 /*** Make sure the device is ready ***/
691 if (!BTM_IsDeviceUp()) {
692 LOG(ERROR) << __func__ << ": adapter is not up";
693 return BTM_WRONG_MODE;
694 }
695
696 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
697 (p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
698 (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
699 (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY) {
700 LOG(ERROR) << __func__ << ": illegal inquiry mode "
701 << std::to_string(p_inqparms->mode);
702 return (BTM_ILLEGAL_VALUE);
703 }
704
705 /* Save the inquiry parameters to be used upon the completion of
706 * setting/clearing the inquiry filter */
707 p_inq->inqparms = *p_inqparms;
708
709 /* Initialize the inquiry variables */
710 p_inq->state = BTM_INQ_ACTIVE_STATE;
711 p_inq->p_inq_cmpl_cb = p_cmpl_cb;
712 p_inq->p_inq_results_cb = p_results_cb;
713 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
714 p_inq->inq_active = p_inqparms->mode;
715
716 BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
717 p_inq->inq_active);
718
719 tBTM_STATUS status = BTM_CMD_STARTED;
720 /* start LE inquiry here if requested */
721 if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)) {
722 if (!controller_get_interface()->supports_ble()) {
723 LOG(ERROR) << __func__ << ": trying to do LE scan on a non-LE adapter";
724 p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
725 status = BTM_ILLEGAL_VALUE;
726 } else {
727 /* BLE for now does not support filter condition for inquiry */
728 status = btm_ble_start_inquiry(
729 (uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
730 p_inqparms->duration);
731 if (status != BTM_CMD_STARTED) {
732 LOG(ERROR) << __func__ << ": Error Starting LE Inquiry";
733 p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
734 }
735 }
736 p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
737
738 BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
739 }
740
741 /* we're done with this routine if BR/EDR inquiry is not desired. */
742 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE) {
743 return status;
744 }
745
746 /* BR/EDR inquiry portion */
747 /* If a filter is specified, then save it for later and clear the current
748 filter.
749 The setting of the filter is done upon completion of clearing of the
750 previous
751 filter.
752 */
753 switch (p_inqparms->filter_cond_type) {
754 case BTM_CLR_INQUIRY_FILTER:
755 p_inq->state = BTM_INQ_SET_FILT_STATE;
756 break;
757
758 case BTM_FILTER_COND_DEVICE_CLASS:
759 case BTM_FILTER_COND_BD_ADDR:
760 /* The filter is not being used so simply clear it;
761 the inquiry can start after this operation */
762 p_inq->state = BTM_INQ_CLR_FILT_STATE;
763 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
764 /* =============>>>> adding LE filtering here ????? */
765 break;
766
767 default:
768 LOG(ERROR) << __func__ << ": invalid filter condition type "
769 << std::to_string(p_inqparms->filter_cond_type);
770 return (BTM_ILLEGAL_VALUE);
771 }
772
773 /* Before beginning the inquiry the current filter must be cleared, so
774 * initiate the command */
775 status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
776 &p_inqparms->filter_cond);
777 if (status != BTM_CMD_STARTED) {
778 LOG(ERROR) << __func__ << ": failed to set inquiry event filter";
779 p_inq->state = BTM_INQ_INACTIVE_STATE;
780 }
781
782 return (status);
783 }
784
785 /*******************************************************************************
786 *
787 * Function BTM_ReadRemoteDeviceName
788 *
789 * Description This function initiates a remote device HCI command to the
790 * controller and calls the callback when the process has
791 * completed.
792 *
793 * Input Params: remote_bda - device address of name to retrieve
794 * p_cb - callback function called when
795 * BTM_CMD_STARTED is returned.
796 * A pointer to tBTM_REMOTE_DEV_NAME is
797 * passed to the callback.
798 *
799 * Returns
800 * BTM_CMD_STARTED is returned if the request was successfully
801 * sent to HCI.
802 * BTM_BUSY if already in progress
803 * BTM_UNKNOWN_ADDR if device address is bad
804 * BTM_NO_RESOURCES if could not allocate resources to start
805 * the command
806 * BTM_WRONG_MODE if the device is not up.
807 *
808 ******************************************************************************/
BTM_ReadRemoteDeviceName(const RawAddress & remote_bda,tBTM_CMPL_CB * p_cb,tBT_TRANSPORT transport)809 tBTM_STATUS BTM_ReadRemoteDeviceName(const RawAddress& remote_bda,
810 tBTM_CMPL_CB* p_cb,
811 tBT_TRANSPORT transport) {
812 if (bluetooth::shim::is_gd_shim_enabled()) {
813 return bluetooth::shim::BTM_ReadRemoteDeviceName(remote_bda, p_cb,
814 transport);
815 }
816
817 VLOG(1) << __func__ << ": bd addr " << remote_bda;
818 /* Use LE transport when LE is the only available option */
819 if (transport == BT_TRANSPORT_LE) {
820 return btm_ble_read_remote_name(remote_bda, p_cb);
821 }
822 /* Use classic transport for BR/EDR and Dual Mode devices */
823 return btm_initiate_rem_name(remote_bda, BTM_RMT_NAME_EXT,
824 BTM_EXT_RMT_NAME_TIMEOUT_MS, p_cb);
825 }
826
827 /*******************************************************************************
828 *
829 * Function BTM_CancelRemoteDeviceName
830 *
831 * Description This function initiates the cancel request for the specified
832 * remote device.
833 *
834 * Input Params: None
835 *
836 * Returns
837 * BTM_CMD_STARTED is returned if the request was successfully
838 * sent to HCI.
839 * BTM_NO_RESOURCES if could not allocate resources to start
840 * the command
841 * BTM_WRONG_MODE if there is not an active remote name
842 * request.
843 *
844 ******************************************************************************/
BTM_CancelRemoteDeviceName(void)845 tBTM_STATUS BTM_CancelRemoteDeviceName(void) {
846 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
847
848 BTM_TRACE_API("BTM_CancelRemoteDeviceName()");
849
850 /* Make sure there is not already one in progress */
851 if (p_inq->remname_active) {
852 if (BTM_UseLeLink(p_inq->remname_bda)) {
853 /* Cancel remote name request for LE device, and process remote name
854 * callback. */
855 btm_inq_rmt_name_failed_cancelled();
856 } else
857 btsnd_hcic_rmt_name_req_cancel(p_inq->remname_bda);
858 return (BTM_CMD_STARTED);
859 } else
860 return (BTM_WRONG_MODE);
861 }
862
863 /*******************************************************************************
864 *
865 * Function BTM_InqDbRead
866 *
867 * Description This function looks through the inquiry database for a match
868 * based on Bluetooth Device Address. This is the application's
869 * interface to get the inquiry details of a specific BD
870 * address.
871 *
872 * Returns pointer to entry, or NULL if not found
873 *
874 ******************************************************************************/
BTM_InqDbRead(const RawAddress & p_bda)875 tBTM_INQ_INFO* BTM_InqDbRead(const RawAddress& p_bda) {
876 VLOG(1) << __func__ << ": bd addr " << p_bda;
877
878 tINQ_DB_ENT* p_ent = btm_inq_db_find(p_bda);
879 if (!p_ent) return NULL;
880
881 return &p_ent->inq_info;
882 }
883
884 /*******************************************************************************
885 *
886 * Function BTM_InqDbFirst
887 *
888 * Description This function looks through the inquiry database for the
889 * first used entry, and returns that. This is used in
890 * conjunction with
891 * BTM_InqDbNext by applications as a way to walk through the
892 * inquiry database.
893 *
894 * Returns pointer to first in-use entry, or NULL if DB is empty
895 *
896 ******************************************************************************/
BTM_InqDbFirst(void)897 tBTM_INQ_INFO* BTM_InqDbFirst(void) {
898 uint16_t xx;
899 tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
900
901 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
902 if (p_ent->in_use) return (&p_ent->inq_info);
903 }
904
905 /* If here, no used entry found */
906 return ((tBTM_INQ_INFO*)NULL);
907 }
908
909 /*******************************************************************************
910 *
911 * Function BTM_InqDbNext
912 *
913 * Description This function looks through the inquiry database for the
914 * next used entry, and returns that. If the input parameter
915 * is NULL, the first entry is returned.
916 *
917 * Returns pointer to next in-use entry, or NULL if no more found.
918 *
919 ******************************************************************************/
BTM_InqDbNext(tBTM_INQ_INFO * p_cur)920 tBTM_INQ_INFO* BTM_InqDbNext(tBTM_INQ_INFO* p_cur) {
921 tINQ_DB_ENT* p_ent;
922 uint16_t inx;
923
924 if (p_cur) {
925 p_ent = (tINQ_DB_ENT*)((uint8_t*)p_cur - offsetof(tINQ_DB_ENT, inq_info));
926 inx = (uint16_t)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
927
928 for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE;
929 inx++, p_ent++) {
930 if (p_ent->in_use) return (&p_ent->inq_info);
931 }
932
933 /* If here, more entries found */
934 return ((tBTM_INQ_INFO*)NULL);
935 } else
936 return (BTM_InqDbFirst());
937 }
938
939 /*******************************************************************************
940 *
941 * Function BTM_ClearInqDb
942 *
943 * Description This function is called to clear out a device or all devices
944 * from the inquiry database.
945 *
946 * Parameter p_bda - (input) BD_ADDR -> Address of device to clear
947 * (NULL clears all entries)
948 *
949 * Returns BTM_BUSY if an inquiry, get remote name, or event filter
950 * is active, otherwise BTM_SUCCESS
951 *
952 ******************************************************************************/
BTM_ClearInqDb(const RawAddress * p_bda)953 tBTM_STATUS BTM_ClearInqDb(const RawAddress* p_bda) {
954 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
955
956 /* If an inquiry or remote name is in progress return busy */
957 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE || p_inq->inqfilt_active)
958 return (BTM_BUSY);
959
960 btm_clr_inq_db(p_bda);
961
962 return (BTM_SUCCESS);
963 }
964
965 /*******************************************************************************
966 *******************************************************************************
967 * **
968 * BTM Internal Inquiry Functions **
969 * **
970 *******************************************************************************
971 ******************************************************************************/
972 /*******************************************************************************
973 *
974 * Function btm_inq_db_reset
975 *
976 * Description This function is called at at reset to clear the inquiry
977 * database & pending callback.
978 *
979 * Returns void
980 *
981 ******************************************************************************/
btm_inq_db_reset(void)982 void btm_inq_db_reset(void) {
983 tBTM_REMOTE_DEV_NAME rem_name;
984 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
985 uint8_t num_responses;
986 uint8_t temp_inq_active;
987 tBTM_STATUS status;
988
989 /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
990 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE) {
991 temp_inq_active = p_inq->inq_active; /* Save so state can change BEFORE
992 callback is called */
993 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
994
995 /* If not a periodic inquiry, the complete callback must be called to notify
996 * caller */
997 if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
998 temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE) {
999 if (p_inq->p_inq_cmpl_cb) {
1000 num_responses = 0;
1001 (*p_inq->p_inq_cmpl_cb)(&num_responses);
1002 }
1003 }
1004 }
1005
1006 /* Cancel a remote name request if active, and notify the caller (if waiting)
1007 */
1008 if (p_inq->remname_active) {
1009 alarm_cancel(p_inq->remote_name_timer);
1010 p_inq->remname_active = false;
1011 p_inq->remname_bda = RawAddress::kEmpty;
1012
1013 if (p_inq->p_remname_cmpl_cb) {
1014 rem_name.status = BTM_DEV_RESET;
1015
1016 (*p_inq->p_remname_cmpl_cb)(&rem_name);
1017 p_inq->p_remname_cmpl_cb = NULL;
1018 }
1019 }
1020
1021 /* Cancel an inquiry filter request if active, and notify the caller (if
1022 * waiting) */
1023 if (p_inq->inqfilt_active) {
1024 p_inq->inqfilt_active = false;
1025
1026 if (p_inq->p_inqfilter_cmpl_cb) {
1027 status = BTM_DEV_RESET;
1028 (*p_inq->p_inqfilter_cmpl_cb)(&status);
1029 }
1030 }
1031
1032 p_inq->state = BTM_INQ_INACTIVE_STATE;
1033 p_inq->pending_filt_complete_event = 0;
1034 p_inq->p_inq_results_cb = NULL;
1035 btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
1036 btm_clr_inq_result_flt();
1037
1038 p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1039 p_inq->connectable_mode = BTM_NON_CONNECTABLE;
1040 p_inq->page_scan_type = BTM_SCAN_TYPE_STANDARD;
1041 p_inq->inq_scan_type = BTM_SCAN_TYPE_STANDARD;
1042
1043 p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1044 p_inq->connectable_mode |= BTM_BLE_NON_CONNECTABLE;
1045 return;
1046 }
1047
1048 /*******************************************************************************
1049 *
1050 * Function btm_inq_db_init
1051 *
1052 * Description This function is called at startup to initialize the inquiry
1053 * database.
1054 *
1055 * Returns void
1056 *
1057 ******************************************************************************/
btm_inq_db_init(void)1058 void btm_inq_db_init(void) {
1059 alarm_free(btm_cb.btm_inq_vars.remote_name_timer);
1060 btm_cb.btm_inq_vars.remote_name_timer =
1061 alarm_new("btm_inq.remote_name_timer");
1062 btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1063 }
1064
1065 /*******************************************************************************
1066 *
1067 * Function btm_inq_stop_on_ssp
1068 *
1069 * Description This function is called on incoming SSP
1070 *
1071 * Returns void
1072 *
1073 ******************************************************************************/
btm_inq_stop_on_ssp(void)1074 void btm_inq_stop_on_ssp(void) {
1075 uint8_t normal_active =
1076 (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1077
1078 #if (BTM_INQ_DEBUG == TRUE)
1079 BTM_TRACE_DEBUG(
1080 "btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d "
1081 "inqfilt_active:%d",
1082 btm_cb.btm_inq_vars.no_inc_ssp, btm_cb.btm_inq_vars.inq_active,
1083 btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1084 #endif
1085 if (btm_cb.btm_inq_vars.no_inc_ssp) {
1086 if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1087 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1088 BTM_CancelPeriodicInquiry();
1089 } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1090 /* can not call BTM_CancelInquiry() here. We need to report inquiry
1091 * complete evt */
1092 btsnd_hcic_inq_cancel();
1093 }
1094 }
1095 /* do not allow inquiry to start */
1096 btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1097 }
1098 }
1099
1100 /*******************************************************************************
1101 *
1102 * Function btm_inq_clear_ssp
1103 *
1104 * Description This function is called when pairing_state becomes idle
1105 *
1106 * Returns void
1107 *
1108 ******************************************************************************/
btm_inq_clear_ssp(void)1109 void btm_inq_clear_ssp(void) {
1110 btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1111 }
1112
1113 /*******************************************************************************
1114 *
1115 * Function btm_clr_inq_db
1116 *
1117 * Description This function is called to clear out a device or all devices
1118 * from the inquiry database.
1119 *
1120 * Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1121 * (NULL clears all entries)
1122 *
1123 * Returns void
1124 *
1125 ******************************************************************************/
btm_clr_inq_db(const RawAddress * p_bda)1126 void btm_clr_inq_db(const RawAddress* p_bda) {
1127 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1128 tINQ_DB_ENT* p_ent = p_inq->inq_db;
1129 uint16_t xx;
1130
1131 #if (BTM_INQ_DEBUG == TRUE)
1132 BTM_TRACE_DEBUG("btm_clr_inq_db: inq_active:0x%x state:%d",
1133 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1134 #endif
1135 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1136 if (p_ent->in_use) {
1137 /* If this is the specified BD_ADDR or clearing all devices */
1138 if (p_bda == NULL || (p_ent->inq_info.results.remote_bd_addr == *p_bda)) {
1139 p_ent->in_use = false;
1140 }
1141 }
1142 }
1143 #if (BTM_INQ_DEBUG == TRUE)
1144 BTM_TRACE_DEBUG("inq_active:0x%x state:%d", btm_cb.btm_inq_vars.inq_active,
1145 btm_cb.btm_inq_vars.state);
1146 #endif
1147 }
1148
1149 /*******************************************************************************
1150 *
1151 * Function btm_clr_inq_result_flt
1152 *
1153 * Description This function looks through the bdaddr database for a match
1154 * based on Bluetooth Device Address
1155 *
1156 * Returns true if found, else false (new entry)
1157 *
1158 ******************************************************************************/
btm_clr_inq_result_flt(void)1159 void btm_clr_inq_result_flt(void) {
1160 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1161
1162 osi_free_and_reset((void**)&p_inq->p_bd_db);
1163 p_inq->num_bd_entries = 0;
1164 p_inq->max_bd_entries = 0;
1165 }
1166
1167 /*******************************************************************************
1168 *
1169 * Function btm_inq_find_bdaddr
1170 *
1171 * Description This function looks through the bdaddr database for a match
1172 * based on Bluetooth Device Address
1173 *
1174 * Returns true if found, else false (new entry)
1175 *
1176 ******************************************************************************/
btm_inq_find_bdaddr(const RawAddress & p_bda)1177 bool btm_inq_find_bdaddr(const RawAddress& p_bda) {
1178 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1179 tINQ_BDADDR* p_db = &p_inq->p_bd_db[0];
1180 uint16_t xx;
1181
1182 /* Don't bother searching, database doesn't exist or periodic mode */
1183 if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db)
1184 return (false);
1185
1186 for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1187 if (p_db->bd_addr == p_bda && p_db->inq_count == p_inq->inq_counter)
1188 return (true);
1189 }
1190
1191 if (xx < p_inq->max_bd_entries) {
1192 p_db->inq_count = p_inq->inq_counter;
1193 p_db->bd_addr = p_bda;
1194 p_inq->num_bd_entries++;
1195 }
1196
1197 /* If here, New Entry */
1198 return (false);
1199 }
1200
1201 /*******************************************************************************
1202 *
1203 * Function btm_inq_db_find
1204 *
1205 * Description This function looks through the inquiry database for a match
1206 * based on Bluetooth Device Address
1207 *
1208 * Returns pointer to entry, or NULL if not found
1209 *
1210 ******************************************************************************/
btm_inq_db_find(const RawAddress & p_bda)1211 tINQ_DB_ENT* btm_inq_db_find(const RawAddress& p_bda) {
1212 uint16_t xx;
1213 tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1214
1215 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1216 if (p_ent->in_use && p_ent->inq_info.results.remote_bd_addr == p_bda)
1217 return (p_ent);
1218 }
1219
1220 /* If here, not found */
1221 return (NULL);
1222 }
1223
1224 /*******************************************************************************
1225 *
1226 * Function btm_inq_db_new
1227 *
1228 * Description This function looks through the inquiry database for an
1229 * unused entry. If no entry is free, it allocates the oldest
1230 * entry.
1231 *
1232 * Returns pointer to entry
1233 *
1234 ******************************************************************************/
btm_inq_db_new(const RawAddress & p_bda)1235 tINQ_DB_ENT* btm_inq_db_new(const RawAddress& p_bda) {
1236 uint16_t xx;
1237 tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1238 tINQ_DB_ENT* p_old = btm_cb.btm_inq_vars.inq_db;
1239 uint64_t ot = UINT64_MAX;
1240
1241 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1242 if (!p_ent->in_use) {
1243 memset(p_ent, 0, sizeof(tINQ_DB_ENT));
1244 p_ent->inq_info.results.remote_bd_addr = p_bda;
1245 p_ent->in_use = true;
1246
1247 return (p_ent);
1248 }
1249
1250 if (p_ent->time_of_resp < ot) {
1251 p_old = p_ent;
1252 ot = p_ent->time_of_resp;
1253 }
1254 }
1255
1256 /* If here, no free entry found. Return the oldest. */
1257
1258 memset(p_old, 0, sizeof(tINQ_DB_ENT));
1259 p_old->inq_info.results.remote_bd_addr = p_bda;
1260 p_old->in_use = true;
1261
1262 return (p_old);
1263 }
1264
1265 /*******************************************************************************
1266 *
1267 * Function btm_set_inq_event_filter
1268 *
1269 * Description This function is called to set the inquiry event filter.
1270 * It is called by either internally, or by the external API
1271 * function (BTM_SetInqEventFilter). It is used internally as
1272 * part of the inquiry processing.
1273 *
1274 * Input Params:
1275 * filter_cond_type - this is the type of inquiry filter to
1276 * apply:
1277 * BTM_FILTER_COND_DEVICE_CLASS,
1278 * BTM_FILTER_COND_BD_ADDR, or
1279 * BTM_CLR_INQUIRY_FILTER
1280 *
1281 * p_filt_cond - this is either a BD_ADDR or DEV_CLASS
1282 * depending on the filter_cond_type
1283 * (See section 4.7.3 of Core Spec 1.0b).
1284 *
1285 * Returns BTM_CMD_STARTED if successfully initiated
1286 * BTM_NO_RESOURCES if couldn't get a memory pool buffer
1287 * BTM_ILLEGAL_VALUE if a bad parameter was detected
1288 *
1289 ******************************************************************************/
btm_set_inq_event_filter(uint8_t filter_cond_type,tBTM_INQ_FILT_COND * p_filt_cond)1290 static tBTM_STATUS btm_set_inq_event_filter(uint8_t filter_cond_type,
1291 tBTM_INQ_FILT_COND* p_filt_cond) {
1292 uint8_t condition_length = DEV_CLASS_LEN * 2;
1293 uint8_t condition_buf[DEV_CLASS_LEN * 2];
1294 uint8_t* p_cond = condition_buf; /* points to the condition to pass to HCI */
1295
1296 #if (BTM_INQ_DEBUG == TRUE)
1297 BTM_TRACE_DEBUG(
1298 "btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
1299 filter_cond_type);
1300 VLOG(2) << "condition " << p_filt_cond->bdaddr_cond;
1301 #endif
1302
1303 /* Load the correct filter condition to pass to the lower layer */
1304 switch (filter_cond_type) {
1305 case BTM_FILTER_COND_DEVICE_CLASS:
1306 /* copy the device class and device class fields into contiguous memory to
1307 * send to HCI */
1308 memcpy(condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1309 memcpy(&condition_buf[DEV_CLASS_LEN],
1310 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1311
1312 /* condition length should already be set as the default */
1313 break;
1314
1315 case BTM_FILTER_COND_BD_ADDR:
1316 p_cond = (uint8_t*)&p_filt_cond->bdaddr_cond;
1317
1318 /* condition length should already be set as the default */
1319 break;
1320
1321 case BTM_CLR_INQUIRY_FILTER:
1322 condition_length = 0;
1323 break;
1324
1325 default:
1326 return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1327 }
1328
1329 btm_cb.btm_inq_vars.inqfilt_active = true;
1330
1331 /* Filter the inquiry results for the specified condition type and value */
1332 btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1333 p_cond, condition_length);
1334 return (BTM_CMD_STARTED);
1335 }
1336
1337 /*******************************************************************************
1338 *
1339 * Function btm_event_filter_complete
1340 *
1341 * Description This function is called when a set event filter has
1342 * completed.
1343 * Note: This routine currently only handles inquiry filters.
1344 * Connection filters are ignored for now.
1345 *
1346 * Returns void
1347 *
1348 ******************************************************************************/
btm_event_filter_complete(uint8_t * p)1349 void btm_event_filter_complete(uint8_t* p) {
1350 uint8_t hci_status;
1351 tBTM_STATUS status;
1352 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1353 tBTM_CMPL_CB* p_cb = p_inq->p_inqfilter_cmpl_cb;
1354
1355 #if (BTM_INQ_DEBUG == TRUE)
1356 BTM_TRACE_DEBUG(
1357 "btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d",
1358 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1359 btm_cb.btm_inq_vars.inqfilt_active);
1360 #endif
1361 /* If the filter complete event is from an old or cancelled request, ignore it
1362 */
1363 if (p_inq->pending_filt_complete_event) {
1364 p_inq->pending_filt_complete_event--;
1365 return;
1366 }
1367
1368 /* Only process the inquiry filter; Ignore the connection filter until it
1369 is used by the upper layers */
1370 if (p_inq->inqfilt_active) {
1371 /* Extract the returned status from the buffer */
1372 STREAM_TO_UINT8(hci_status, p);
1373 if (hci_status != HCI_SUCCESS) {
1374 /* If standalone operation, return the error status; if embedded in the
1375 * inquiry, continue the inquiry */
1376 BTM_TRACE_WARNING(
1377 "BTM Warning: Set Event Filter Failed (HCI returned 0x%x)",
1378 hci_status);
1379 status = BTM_ERR_PROCESSING;
1380 } else
1381 status = BTM_SUCCESS;
1382
1383 /* If the set filter was initiated externally (via BTM_SetInqEventFilter),
1384 call the
1385 callback function to notify the initiator that it has completed */
1386 if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1387 p_inq->inqfilt_active = false;
1388 if (p_cb) (*p_cb)(&status);
1389 } else /* An inquiry is active (the set filter command was internally
1390 generated),
1391 process the next state of the process (Set a new filter or start
1392 the inquiry). */
1393 {
1394 if (status != BTM_SUCCESS) {
1395 /* Process the inquiry complete (Error Status) */
1396 btm_process_inq_complete(
1397 BTM_ERR_PROCESSING,
1398 (uint8_t)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1399
1400 /* btm_process_inq_complete() does not restore the following settings on
1401 * periodic inquiry */
1402 p_inq->inqfilt_active = false;
1403 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1404 p_inq->state = BTM_INQ_INACTIVE_STATE;
1405
1406 return;
1407 }
1408
1409 /* Check to see if a new filter needs to be set up */
1410 if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1411 status = btm_set_inq_event_filter(p_inq->inqparms.filter_cond_type,
1412 &p_inq->inqparms.filter_cond);
1413 if (status == BTM_CMD_STARTED) {
1414 p_inq->state = BTM_INQ_SET_FILT_STATE;
1415 } else /* Error setting the filter: Call the initiator's callback
1416 function to indicate a failure */
1417 {
1418 p_inq->inqfilt_active = false;
1419
1420 /* Process the inquiry complete (Error Status) */
1421 btm_process_inq_complete(
1422 BTM_ERR_PROCESSING,
1423 (uint8_t)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1424 }
1425 } else /* Initiate the Inquiry or Periodic Inquiry */
1426 {
1427 p_inq->state = BTM_INQ_ACTIVE_STATE;
1428 p_inq->inqfilt_active = false;
1429 btm_initiate_inquiry(p_inq);
1430 }
1431 }
1432 }
1433 }
1434
1435 /*******************************************************************************
1436 *
1437 * Function btm_initiate_inquiry
1438 *
1439 * Description This function is called to start an inquiry or periodic
1440 * inquiry upon completion of the setting and/or clearing of
1441 * the inquiry filter.
1442 *
1443 * Inputs: p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry
1444 * information
1445 * mode - GENERAL or LIMITED inquiry
1446 * duration - length in 1.28 sec intervals
1447 * (If '0', the inquiry is CANCELLED)
1448 * max_resps - maximum amount of devices to search for
1449 * before ending the inquiry
1450 * filter_cond_type - BTM_CLR_INQUIRY_FILTER,
1451 * BTM_FILTER_COND_DEVICE_CLASS, or
1452 * BTM_FILTER_COND_BD_ADDR
1453 * filter_cond - value for the filter
1454 * (based on filter_cond_type)
1455 *
1456 * Returns If an error occurs the initiator's callback is called with
1457 * the error status.
1458 *
1459 ******************************************************************************/
btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST * p_inq)1460 static void btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST* p_inq) {
1461 const LAP* lap;
1462 tBTM_INQ_PARMS* p_inqparms = &p_inq->inqparms;
1463
1464 #if (BTM_INQ_DEBUG == TRUE)
1465 BTM_TRACE_DEBUG(
1466 "btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d",
1467 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1468 btm_cb.btm_inq_vars.inqfilt_active);
1469 #endif
1470 btm_acl_update_busy_level(BTM_BLI_INQ_EVT);
1471
1472 if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1473 btm_process_inq_complete(BTM_NO_RESOURCES,
1474 (uint8_t)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1475 return;
1476 }
1477
1478 /* Make sure the number of responses doesn't overflow the database
1479 * configuration */
1480 p_inqparms->max_resps = (uint8_t)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE)
1481 ? p_inqparms->max_resps
1482 : BTM_INQ_DB_SIZE);
1483
1484 lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap
1485 : &general_inq_lap;
1486
1487 if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1488 btsnd_hcic_per_inq_mode(p_inq->per_max_delay, p_inq->per_min_delay, *lap,
1489 p_inqparms->duration, p_inqparms->max_resps);
1490 } else {
1491 btm_clr_inq_result_flt();
1492
1493 /* Allocate memory to hold bd_addrs responding */
1494 p_inq->p_bd_db = (tINQ_BDADDR*)osi_calloc(BT_DEFAULT_BUFFER_SIZE);
1495 p_inq->max_bd_entries =
1496 (uint16_t)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1497
1498 btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0);
1499 }
1500 }
1501
1502 /*******************************************************************************
1503 *
1504 * Function btm_process_inq_results
1505 *
1506 * Description This function is called when inquiry results are received
1507 * from the device. It updates the inquiry database. If the
1508 * inquiry database is full, the oldest entry is discarded.
1509 *
1510 * Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
1511 * BTM_INQ_RESULT_WITH_RSSI
1512 * BTM_INQ_RESULT_EXTENDED
1513 *
1514 * Returns void
1515 *
1516 ******************************************************************************/
btm_process_inq_results(uint8_t * p,uint8_t hci_evt_len,uint8_t inq_res_mode)1517 void btm_process_inq_results(uint8_t* p, uint8_t hci_evt_len,
1518 uint8_t inq_res_mode) {
1519 uint8_t num_resp, xx;
1520 RawAddress bda;
1521 tINQ_DB_ENT* p_i;
1522 tBTM_INQ_RESULTS* p_cur = NULL;
1523 bool is_new = true;
1524 bool update = false;
1525 int8_t i_rssi;
1526 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1527 tBTM_INQ_RESULTS_CB* p_inq_results_cb = p_inq->p_inq_results_cb;
1528 uint8_t page_scan_rep_mode = 0;
1529 uint8_t page_scan_per_mode = 0;
1530 uint8_t page_scan_mode = 0;
1531 uint8_t rssi = 0;
1532 DEV_CLASS dc;
1533 uint16_t clock_offset;
1534 uint8_t* p_eir_data = NULL;
1535
1536 #if (BTM_INQ_DEBUG == TRUE)
1537 BTM_TRACE_DEBUG(
1538 "btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
1539 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1540 btm_cb.btm_inq_vars.inqfilt_active);
1541 #endif
1542 /* Only process the results if the BR inquiry is still active */
1543 if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) return;
1544
1545 STREAM_TO_UINT8(num_resp, p);
1546
1547 if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
1548 if (num_resp > 1) {
1549 BTM_TRACE_ERROR("btm_process_inq_results() extended results (%d) > 1",
1550 num_resp);
1551 return;
1552 }
1553
1554 constexpr uint16_t extended_inquiry_result_size = 254;
1555 if (hci_evt_len - 1 != extended_inquiry_result_size) {
1556 android_errorWriteLog(0x534e4554, "141620271");
1557 BTM_TRACE_ERROR("%s: can't fit %d results in %d bytes", __func__,
1558 num_resp, hci_evt_len);
1559 return;
1560 }
1561 } else if (inq_res_mode == BTM_INQ_RESULT_STANDARD ||
1562 inq_res_mode == BTM_INQ_RESULT_WITH_RSSI) {
1563 constexpr uint16_t inquiry_result_size = 14;
1564 if (hci_evt_len < num_resp * inquiry_result_size) {
1565 android_errorWriteLog(0x534e4554, "141620271");
1566 BTM_TRACE_ERROR("%s: can't fit %d results in %d bytes", __func__,
1567 num_resp, hci_evt_len);
1568 return;
1569 }
1570 }
1571
1572 for (xx = 0; xx < num_resp; xx++) {
1573 update = false;
1574 /* Extract inquiry results */
1575 STREAM_TO_BDADDR(bda, p);
1576 STREAM_TO_UINT8(page_scan_rep_mode, p);
1577 STREAM_TO_UINT8(page_scan_per_mode, p);
1578
1579 if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1580 STREAM_TO_UINT8(page_scan_mode, p);
1581 }
1582
1583 STREAM_TO_DEVCLASS(dc, p);
1584 STREAM_TO_UINT16(clock_offset, p);
1585 if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1586 STREAM_TO_UINT8(rssi, p);
1587 }
1588
1589 p_i = btm_inq_db_find(bda);
1590 /* Only process the num_resp is smaller than max_resps.
1591 If results are queued to BTU task while canceling inquiry,
1592 or when more than one result is in this response, > max_resp
1593 responses could be processed which can confuse some apps
1594 */
1595 if (p_inq->inqparms.max_resps &&
1596 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1597 /* new device response */
1598 &&
1599 (p_i == NULL ||
1600 /* exisiting device with BR/EDR info */
1601 (p_i &&
1602 (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0))) {
1603 /* BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring"); */
1604 return;
1605 }
1606
1607 /* Check if this address has already been processed for this inquiry */
1608 if (btm_inq_find_bdaddr(bda)) {
1609 /* BTM_TRACE_DEBUG("BDA seen before %s", bda.ToString().c_str()); */
1610
1611 /* By default suppose no update needed */
1612 i_rssi = (int8_t)rssi;
1613
1614 /* If this new RSSI is higher than the last one */
1615 if (p_inq->inqparms.report_dup && (rssi != 0) && p_i &&
1616 (i_rssi > p_i->inq_info.results.rssi ||
1617 p_i->inq_info.results.rssi == 0
1618 /* BR/EDR inquiry information update */
1619 ||
1620 (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)) {
1621 p_cur = &p_i->inq_info.results;
1622 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);
1623 p_cur->rssi = i_rssi;
1624 update = true;
1625 }
1626 /* If we received a second Extended Inq Event for an already */
1627 /* discovered device, this is because for the first one EIR was not
1628 received */
1629 else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1630 p_cur = &p_i->inq_info.results;
1631 update = true;
1632 }
1633 /* If no update needed continue with next response (if any) */
1634 else
1635 continue;
1636 }
1637
1638 /* If existing entry, use that, else get a new one (possibly reusing the
1639 * oldest) */
1640 if (p_i == NULL) {
1641 p_i = btm_inq_db_new(bda);
1642 is_new = true;
1643 }
1644
1645 /* If an entry for the device already exists, overwrite it ONLY if it is
1646 from
1647 a previous inquiry. (Ignore it if it is a duplicate response from the
1648 same
1649 inquiry.
1650 */
1651 else if (p_i->inq_count == p_inq->inq_counter &&
1652 (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR))
1653 is_new = false;
1654
1655 /* keep updating RSSI to have latest value */
1656 if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
1657 p_i->inq_info.results.rssi = (int8_t)rssi;
1658 else
1659 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1660
1661 if (is_new) {
1662 /* Save the info */
1663 p_cur = &p_i->inq_info.results;
1664 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1665 p_cur->page_scan_per_mode = page_scan_per_mode;
1666 p_cur->page_scan_mode = page_scan_mode;
1667 p_cur->dev_class[0] = dc[0];
1668 p_cur->dev_class[1] = dc[1];
1669 p_cur->dev_class[2] = dc[2];
1670 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1671
1672 p_i->time_of_resp = bluetooth::common::time_get_os_boottime_ms();
1673
1674 if (p_i->inq_count != p_inq->inq_counter)
1675 p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
1676
1677 p_cur->inq_result_type |= BTM_INQ_RESULT_BR;
1678 if (p_i->inq_count != p_inq->inq_counter) {
1679 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1680 p_i->scan_rsp = false;
1681 } else
1682 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1683 p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
1684
1685 /* If the number of responses found and not unlimited, issue a cancel
1686 * inquiry */
1687 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1688 p_inq->inqparms.max_resps &&
1689 p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps &&
1690 /* BLE scanning is active and received adv */
1691 ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1692 p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1693 (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)) {
1694 /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling
1695 * inquiry..."); */
1696 btsnd_hcic_inq_cancel();
1697
1698 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
1699 btm_ble_stop_inquiry();
1700 btm_acl_update_busy_level(BTM_BLI_INQ_DONE_EVT);
1701 }
1702 /* Initialize flag to false. This flag is set/used by application */
1703 p_i->inq_info.appl_knows_rem_name = false;
1704 }
1705
1706 if (is_new || update) {
1707 if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
1708 memset(p_cur->eir_uuid, 0,
1709 BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
1710 /* set bit map of UUID list from received EIR */
1711 btm_set_eir_uuid(p, p_cur);
1712 p_eir_data = p;
1713 } else
1714 p_eir_data = NULL;
1715
1716 /* If a callback is registered, call it with the results */
1717 if (p_inq_results_cb) {
1718 (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data,
1719 HCI_EXT_INQ_RESPONSE_LEN);
1720 } else {
1721 BTM_TRACE_DEBUG("No callback is registered");
1722 }
1723 }
1724 }
1725 }
1726
1727 /*******************************************************************************
1728 *
1729 * Function btm_sort_inq_result
1730 *
1731 * Description This function is called when inquiry complete is received
1732 * from the device to sort inquiry results based on rssi.
1733 *
1734 * Returns void
1735 *
1736 ******************************************************************************/
btm_sort_inq_result(void)1737 void btm_sort_inq_result(void) {
1738 uint8_t xx, yy, num_resp;
1739 tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
1740 tINQ_DB_ENT* p_next = btm_cb.btm_inq_vars.inq_db + 1;
1741 int size;
1742 tINQ_DB_ENT* p_tmp = (tINQ_DB_ENT*)osi_malloc(sizeof(tINQ_DB_ENT));
1743
1744 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE)
1745 ? btm_cb.btm_inq_vars.inq_cmpl_info.num_resp
1746 : BTM_INQ_DB_SIZE;
1747
1748 size = sizeof(tINQ_DB_ENT);
1749 for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
1750 for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
1751 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
1752 memcpy(p_tmp, p_next, size);
1753 memcpy(p_next, p_ent, size);
1754 memcpy(p_ent, p_tmp, size);
1755 }
1756 }
1757 }
1758
1759 osi_free(p_tmp);
1760 }
1761
1762 /*******************************************************************************
1763 *
1764 * Function btm_process_inq_complete
1765 *
1766 * Description This function is called when inquiry complete is received
1767 * from the device. Call the callback if not in periodic
1768 * inquiry mode AND it is not NULL
1769 * (The caller wants the event).
1770 *
1771 * The callback pass back the status and the number of
1772 * responses
1773 *
1774 * Returns void
1775 *
1776 ******************************************************************************/
btm_process_inq_complete(uint8_t status,uint8_t mode)1777 void btm_process_inq_complete(uint8_t status, uint8_t mode) {
1778 tBTM_CMPL_CB* p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
1779 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1780
1781 p_inq->inqparms.mode &= ~(mode);
1782
1783 #if (BTM_INQ_DEBUG == TRUE)
1784 BTM_TRACE_DEBUG(
1785 "btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d",
1786 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1787 btm_cb.btm_inq_vars.inqfilt_active);
1788 #endif
1789 btm_acl_update_busy_level(BTM_BLI_INQ_DONE_EVT);
1790 /* Ignore any stray or late complete messages if the inquiry is not active */
1791 if (p_inq->inq_active) {
1792 p_inq->inq_cmpl_info.status = (tBTM_STATUS)(
1793 (status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
1794
1795 /* Notify caller that the inquiry has completed; (periodic inquiries do not
1796 * send completion events */
1797 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1798 p_inq->inqparms.mode == 0) {
1799 btm_clear_all_pending_le_entry();
1800 p_inq->state = BTM_INQ_INACTIVE_STATE;
1801
1802 /* Increment so the start of a next inquiry has a new count */
1803 p_inq->inq_counter++;
1804
1805 btm_clr_inq_result_flt();
1806
1807 if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
1808 controller_get_interface()->supports_rssi_with_inquiry_results()) {
1809 btm_sort_inq_result();
1810 }
1811
1812 /* Clear the results callback if set */
1813 p_inq->p_inq_results_cb = NULL;
1814 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1815 p_inq->p_inq_cmpl_cb = NULL;
1816
1817 /* If we have a callback registered for inquiry complete, call it */
1818 BTM_TRACE_DEBUG("BTM Inq Compl Callback: status 0x%02x, num results %d",
1819 p_inq->inq_cmpl_info.status,
1820 p_inq->inq_cmpl_info.num_resp);
1821
1822 if (p_inq_cb) (p_inq_cb)((tBTM_INQUIRY_CMPL*)&p_inq->inq_cmpl_info);
1823 }
1824 }
1825 if (p_inq->inqparms.mode == 0 &&
1826 p_inq->scan_type == INQ_GENERAL) // this inquiry is complete
1827 {
1828 p_inq->scan_type = INQ_NONE;
1829 }
1830 #if (BTM_INQ_DEBUG == TRUE)
1831 BTM_TRACE_DEBUG("inq_active:0x%x state:%d inqfilt_active:%d",
1832 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state,
1833 btm_cb.btm_inq_vars.inqfilt_active);
1834 #endif
1835 }
1836
1837 /*******************************************************************************
1838 *
1839 * Function btm_process_cancel_complete
1840 *
1841 * Description This function is called when inquiry cancel complete is
1842 * received from the device. This function will also call the
1843 * btm_process_inq_complete. This function is needed to
1844 * differentiate a cancel_cmpl_evt from the inq_cmpl_evt.
1845 *
1846 * Returns void
1847 *
1848 ******************************************************************************/
btm_process_cancel_complete(uint8_t status,uint8_t mode)1849 void btm_process_cancel_complete(uint8_t status, uint8_t mode) {
1850 btm_acl_update_busy_level(BTM_BLI_INQ_CANCEL_EVT);
1851 btm_process_inq_complete(status, mode);
1852 }
1853 /*******************************************************************************
1854 *
1855 * Function btm_initiate_rem_name
1856 *
1857 * Description This function looks initiates a remote name request. It is
1858 * called either by GAP or by the API call
1859 * BTM_ReadRemoteDeviceName.
1860 *
1861 * Input Params: p_cb - callback function called when
1862 * BTM_CMD_STARTED is returned.
1863 * A pointer to tBTM_REMOTE_DEV_NAME is
1864 * passed to the callback.
1865 *
1866 * Returns
1867 * BTM_CMD_STARTED is returned if the request was sent to HCI.
1868 * BTM_BUSY if already in progress
1869 * BTM_NO_RESOURCES if could not allocate resources to start
1870 * the command
1871 * BTM_WRONG_MODE if the device is not up.
1872 *
1873 ******************************************************************************/
btm_initiate_rem_name(const RawAddress & remote_bda,uint8_t origin,uint64_t timeout_ms,tBTM_CMPL_CB * p_cb)1874 tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda, uint8_t origin,
1875 uint64_t timeout_ms, tBTM_CMPL_CB* p_cb) {
1876 tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
1877
1878 /*** Make sure the device is ready ***/
1879 if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
1880 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 the 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