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