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