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