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