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