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