1 /******************************************************************************
3 * Copyright (C) 1999-2014 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
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
26 ******************************************************************************/
32 #include "osi/alarm.h"
33 #include "stack/bt_types.h"
34 #include "device/controller.h"
35 #include "stack/hcimsgs.h"
36 #include "stack/btu.h"
37 #include "stack/btm_api.h"
39 #include "stack/hcidefs.h"
40 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
41 #include "stack/sdpdefs.h"
44 #define BTM_INQ_REPLY_TIMEOUT 3 /* 3 second timeout waiting for responses */
46 /* TRUE to enable DEBUG traces for btm_inq */
48 #define BTM_INQ_DEBUG FALSE
50 /********************************************************************************/
51 /* L O C A L D A T A D E F I N I T I O N S */
52 /********************************************************************************/
53 static const LAP general_inq_lap = {0x9e, 0x8b, 0x33};
54 static const LAP limited_inq_lap = {0x9e, 0x8b, 0x00};
56 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
57 static const UINT16 BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES] = {
58 UUID_SERVCLASS_SERVICE_DISCOVERY_SERVER,
59 /* UUID_SERVCLASS_BROWSE_GROUP_DESCRIPTOR, */
60 /* UUID_SERVCLASS_PUBLIC_BROWSE_GROUP, */
61 UUID_SERVCLASS_SERIAL_PORT,
62 UUID_SERVCLASS_LAN_ACCESS_USING_PPP,
63 UUID_SERVCLASS_DIALUP_NETWORKING,
64 UUID_SERVCLASS_IRMC_SYNC,
65 UUID_SERVCLASS_OBEX_OBJECT_PUSH,
66 UUID_SERVCLASS_OBEX_FILE_TRANSFER,
67 UUID_SERVCLASS_IRMC_SYNC_COMMAND,
68 UUID_SERVCLASS_HEADSET,
69 UUID_SERVCLASS_CORDLESS_TELEPHONY,
70 UUID_SERVCLASS_AUDIO_SOURCE,
71 UUID_SERVCLASS_AUDIO_SINK,
72 UUID_SERVCLASS_AV_REM_CTRL_TARGET,
73 /* UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, */
74 UUID_SERVCLASS_AV_REMOTE_CONTROL,
75 /* UUID_SERVCLASS_VIDEO_CONFERENCING, */
76 UUID_SERVCLASS_INTERCOM,
78 UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
79 /* UUID_SERVCLASS_WAP, */
80 /* UUID_SERVCLASS_WAP_CLIENT, */
84 UUID_SERVCLASS_DIRECT_PRINTING,
85 /* UUID_SERVCLASS_REFERENCE_PRINTING, */
86 UUID_SERVCLASS_IMAGING,
87 UUID_SERVCLASS_IMAGING_RESPONDER,
88 UUID_SERVCLASS_IMAGING_AUTO_ARCHIVE,
89 UUID_SERVCLASS_IMAGING_REF_OBJECTS,
90 UUID_SERVCLASS_HF_HANDSFREE,
91 UUID_SERVCLASS_AG_HANDSFREE,
92 UUID_SERVCLASS_DIR_PRT_REF_OBJ_SERVICE,
93 /* UUID_SERVCLASS_REFLECTED_UI, */
94 UUID_SERVCLASS_BASIC_PRINTING,
95 UUID_SERVCLASS_PRINTING_STATUS,
96 UUID_SERVCLASS_HUMAN_INTERFACE,
97 UUID_SERVCLASS_CABLE_REPLACEMENT,
98 UUID_SERVCLASS_HCRP_PRINT,
99 UUID_SERVCLASS_HCRP_SCAN,
100 /* UUID_SERVCLASS_COMMON_ISDN_ACCESS, */
101 /* UUID_SERVCLASS_VIDEO_CONFERENCING_GW, */
102 /* UUID_SERVCLASS_UDI_MT, */
103 /* UUID_SERVCLASS_UDI_TA, */
104 /* UUID_SERVCLASS_VCP, */
106 UUID_SERVCLASS_PBAP_PCE,
107 UUID_SERVCLASS_PBAP_PSE,
108 UUID_SERVCLASS_PHONE_ACCESS,
109 UUID_SERVCLASS_HEADSET_HS,
110 UUID_SERVCLASS_PNP_INFORMATION,
111 /* UUID_SERVCLASS_GENERIC_NETWORKING, */
112 /* UUID_SERVCLASS_GENERIC_FILETRANSFER, */
113 /* UUID_SERVCLASS_GENERIC_AUDIO, */
114 /* UUID_SERVCLASS_GENERIC_TELEPHONY, */
115 /* UUID_SERVCLASS_UPNP_SERVICE, */
116 /* UUID_SERVCLASS_UPNP_IP_SERVICE, */
117 /* UUID_SERVCLASS_ESDP_UPNP_IP_PAN, */
118 /* UUID_SERVCLASS_ESDP_UPNP_IP_LAP, */
119 /* UUID_SERVCLASS_ESDP_UPNP_IP_L2CAP, */
120 UUID_SERVCLASS_VIDEO_SOURCE,
121 UUID_SERVCLASS_VIDEO_SINK,
122 /* UUID_SERVCLASS_VIDEO_DISTRIBUTION */
123 UUID_SERVCLASS_MESSAGE_ACCESS,
124 UUID_SERVCLASS_MESSAGE_NOTIFICATION,
125 UUID_SERVCLASS_HDP_SOURCE,
126 UUID_SERVCLASS_HDP_SINK
129 static const UINT16 BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES];
132 /********************************************************************************/
133 /* L O C A L F U N C T I O N P R O T O T Y P E S */
134 /********************************************************************************/
135 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq);
136 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type, tBTM_INQ_FILT_COND *p_filt_cond);
137 static void btm_clr_inq_result_flt (void);
139 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 );
140 static void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results );
141 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
142 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type );
143 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size );
145 /*******************************************************************************
147 ** Function BTM_SetDiscoverability
149 ** Description This function is called to set the device into or out of
150 ** discoverable mode. Discoverable mode means inquiry
151 ** scans are enabled. If a value of '0' is entered for window or
152 ** interval, the default values are used.
154 ** Returns BTM_SUCCESS if successful
155 ** BTM_BUSY if a setting of the filter is already in progress
156 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
157 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
158 ** BTM_WRONG_MODE if the device is not up.
160 *******************************************************************************/
161 tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 interval)
164 UINT16 service_class;
172 BTM_TRACE_API ("BTM_SetDiscoverability\n");
173 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
174 if (controller_get_interface()->supports_ble()) {
175 if (btm_ble_set_discoverability((UINT16)(inq_mode))
177 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
178 btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
181 inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
184 /*** Check mode parameter ***/
185 if (inq_mode > BTM_MAX_DISCOVERABLE) {
186 return (BTM_ILLEGAL_VALUE);
189 /* Make sure the controller is active */
190 if (!controller_get_interface()->get_is_ready()) {
191 return (BTM_DEV_RESET);
194 /* If the window and/or interval is '0', set to default values */
196 window = BTM_DEFAULT_DISC_WINDOW;
200 interval = BTM_DEFAULT_DISC_INTERVAL;
203 BTM_TRACE_API ("BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window 0x%04x, interval 0x%04x\n",
204 inq_mode, window, interval);
206 /*** Check for valid window and interval parameters ***/
207 /*** Only check window and duration if mode is connectable ***/
208 if (inq_mode != BTM_NON_DISCOVERABLE) {
209 /* window must be less than or equal to interval */
210 if (window < HCI_MIN_INQUIRYSCAN_WINDOW ||
211 window > HCI_MAX_INQUIRYSCAN_WINDOW ||
212 interval < HCI_MIN_INQUIRYSCAN_INTERVAL ||
213 interval > HCI_MAX_INQUIRYSCAN_INTERVAL ||
215 return (BTM_ILLEGAL_VALUE);
219 /* Set the IAC if needed */
220 if (inq_mode != BTM_NON_DISCOVERABLE) {
221 if (inq_mode & BTM_LIMITED_DISCOVERABLE) {
222 /* Use the GIAC and LIAC codes for limited discoverable mode */
223 memcpy (temp_lap[0], limited_inq_lap, LAP_LEN);
224 memcpy (temp_lap[1], general_inq_lap, LAP_LEN);
226 if (!btsnd_hcic_write_cur_iac_lap (2, (LAP * const) temp_lap)) {
227 return (BTM_NO_RESOURCES); /* Cannot continue */
230 if (!btsnd_hcic_write_cur_iac_lap (1, (LAP * const) &general_inq_lap)) {
231 return (BTM_NO_RESOURCES); /* Cannot continue */
235 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
238 /* Send down the inquiry scan window and period if changed */
239 if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
240 (interval != btm_cb.btm_inq_vars.inq_scan_period)) {
241 if (btsnd_hcic_write_inqscan_cfg (interval, window)) {
242 btm_cb.btm_inq_vars.inq_scan_window = window;
243 btm_cb.btm_inq_vars.inq_scan_period = interval;
245 return (BTM_NO_RESOURCES);
249 if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK) {
250 scan_mode |= HCI_PAGE_SCAN_ENABLED;
253 if (btsnd_hcic_write_scan_enable (scan_mode)) {
254 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
255 btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
257 return (BTM_NO_RESOURCES);
260 /* Change the service class bit if mode has changed */
261 p_cod = BTM_ReadDeviceClass();
262 BTM_COD_SERVICE_CLASS(service_class, p_cod);
263 is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? TRUE : FALSE;
264 cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? TRUE : FALSE;
265 if (is_limited ^ cod_limited) {
266 BTM_COD_MINOR_CLASS(minor, p_cod );
267 BTM_COD_MAJOR_CLASS(major, p_cod );
269 service_class |= BTM_COD_SERVICE_LMTD_DISCOVER;
271 service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER;
274 FIELDS_TO_COD(cod, minor, major, service_class);
275 (void) BTM_SetDeviceClass (cod);
278 return (BTM_SUCCESS);
281 /*******************************************************************************
283 ** Function BTM_SetInquiryScanType
285 ** Description This function is called to set the iquiry scan-type to
286 ** standard or interlaced.
288 ** Returns BTM_SUCCESS if successful
289 ** BTM_MODE_UNSUPPORTED if not a 1.2 device
290 ** BTM_WRONG_MODE if the device is not up.
292 *******************************************************************************/
293 tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type)
296 BTM_TRACE_API ("BTM_SetInquiryScanType\n");
297 if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED) {
298 return (BTM_ILLEGAL_VALUE);
301 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
302 if (!controller_get_interface()->supports_interlaced_inquiry_scan()) {
303 return (BTM_MODE_UNSUPPORTED);
306 /* Check for scan type if configuration has been changed */
307 if (scan_type != btm_cb.btm_inq_vars.inq_scan_type) {
308 if (BTM_IsDeviceUp()) {
309 if (btsnd_hcic_write_inqscan_type ((UINT8)scan_type)) {
310 btm_cb.btm_inq_vars.inq_scan_type = scan_type;
312 return (BTM_NO_RESOURCES);
315 return (BTM_WRONG_MODE);
318 return (BTM_SUCCESS);
321 /*******************************************************************************
323 ** Function BTM_SetPageScanType
325 ** Description This function is called to set the page scan-type to
326 ** standard or interlaced.
328 ** Returns BTM_SUCCESS if successful
329 ** BTM_MODE_UNSUPPORTED if not a 1.2 device
330 ** BTM_WRONG_MODE if the device is not up.
332 *******************************************************************************/
333 tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type)
335 BTM_TRACE_API ("BTM_SetPageScanType\n");
336 if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED) {
337 return (BTM_ILLEGAL_VALUE);
340 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
341 if (!controller_get_interface()->supports_interlaced_inquiry_scan()) {
342 return (BTM_MODE_UNSUPPORTED);
345 /* Check for scan type if configuration has been changed */
346 if (scan_type != btm_cb.btm_inq_vars.page_scan_type) {
347 if (BTM_IsDeviceUp()) {
348 if (btsnd_hcic_write_pagescan_type ((UINT8)scan_type)) {
349 btm_cb.btm_inq_vars.page_scan_type = scan_type;
351 return (BTM_NO_RESOURCES);
354 return (BTM_WRONG_MODE);
357 return (BTM_SUCCESS);
361 /*******************************************************************************
363 ** Function BTM_SetInquiryMode
365 ** Description This function is called to set standard or with RSSI
366 ** mode of the inquiry for local device.
368 ** Output Params: mode - standard, with RSSI, extended
370 ** Returns BTM_SUCCESS if successful
371 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
372 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
373 ** BTM_WRONG_MODE if the device is not up.
375 *******************************************************************************/
376 tBTM_STATUS BTM_SetInquiryMode (UINT8 mode)
378 const controller_t *controller = controller_get_interface();
379 BTM_TRACE_API ("BTM_SetInquiryMode\n");
380 if (mode == BTM_INQ_RESULT_STANDARD) {
382 } else if (mode == BTM_INQ_RESULT_WITH_RSSI) {
383 if (!controller->supports_rssi_with_inquiry_results()) {
384 return (BTM_MODE_UNSUPPORTED);
386 } else if (mode == BTM_INQ_RESULT_EXTENDED) {
387 if (!controller->supports_extended_inquiry_response()) {
388 return (BTM_MODE_UNSUPPORTED);
391 return (BTM_ILLEGAL_VALUE);
394 if (!BTM_IsDeviceUp()) {
395 return (BTM_WRONG_MODE);
398 if (!btsnd_hcic_write_inquiry_mode (mode)) {
399 return (BTM_NO_RESOURCES);
402 return (BTM_SUCCESS);
405 /*******************************************************************************
407 ** Function BTM_ReadDiscoverability
409 ** Description This function is called to read the current discoverability
410 ** mode of the device.
412 ** Output Params: p_window - current inquiry scan duration
413 ** p_interval - current inquiry scan interval
415 ** Returns BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
416 ** BTM_GENERAL_DISCOVERABLE
418 *******************************************************************************/
419 UINT16 BTM_ReadDiscoverability (UINT16 *p_window, UINT16 *p_interval)
421 BTM_TRACE_API ("BTM_ReadDiscoverability\n");
423 *p_window = btm_cb.btm_inq_vars.inq_scan_window;
427 *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
430 return (btm_cb.btm_inq_vars.discoverable_mode);
434 /*******************************************************************************
436 ** Function BTM_SetPeriodicInquiryMode
438 ** Description This function is called to set the device periodic inquiry mode.
439 ** If the duration is zero, the periodic inquiry mode is cancelled.
441 ** Note: We currently do not allow concurrent inquiry and periodic inquiry.
443 ** Parameters: p_inqparms - pointer to the inquiry information
444 ** mode - GENERAL or LIMITED inquiry
445 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
446 ** max_resps - maximum amount of devices to search for before ending the inquiry
447 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
448 ** BTM_FILTER_COND_BD_ADDR
449 ** filter_cond - value for the filter (based on filter_cond_type)
451 ** max_delay - maximum amount of time between successive inquiries
452 ** min_delay - minimum amount of time between successive inquiries
453 ** p_results_cb - callback returning pointer to results (tBTM_INQ_RESULTS)
455 ** Returns BTM_CMD_STARTED if successfully started
456 ** BTM_ILLEGAL_VALUE if a bad parameter is detected
457 ** BTM_NO_RESOURCES if could not allocate a message buffer
458 ** BTM_SUCCESS - if cancelling the periodic inquiry
459 ** BTM_BUSY - if an inquiry is already active
460 ** BTM_WRONG_MODE if the device is not up.
462 *******************************************************************************/
463 tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_delay,
464 UINT16 min_delay, tBTM_INQ_RESULTS_CB *p_results_cb)
467 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
469 BTM_TRACE_API ("BTM_SetPeriodicInquiryMode: mode: %d, dur: %d, rsps: %d, flt: %d, min: %d, max: %d\n",
470 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
471 p_inqparms->filter_cond_type, min_delay, max_delay);
473 /*** Make sure the device is ready ***/
474 if (!BTM_IsDeviceUp()) {
475 return (BTM_WRONG_MODE);
478 /* Only one active inquiry is allowed in this implementation.
479 Also do not allow an inquiry if the inquiry filter is being updated */
480 if (p_inq->inq_active || p_inq->inqfilt_active) {
484 /* If illegal parameters return FALSE */
485 if (p_inqparms->mode != BTM_GENERAL_INQUIRY &&
486 p_inqparms->mode != BTM_LIMITED_INQUIRY) {
487 return (BTM_ILLEGAL_VALUE);
490 /* Verify the parameters for this command */
491 if (p_inqparms->duration < BTM_MIN_INQUIRY_LEN ||
492 p_inqparms->duration > BTM_MAX_INQUIRY_LENGTH ||
493 min_delay <= p_inqparms->duration ||
494 min_delay < BTM_PER_INQ_MIN_MIN_PERIOD ||
495 min_delay > BTM_PER_INQ_MAX_MIN_PERIOD ||
496 max_delay <= min_delay ||
497 max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
498 /* max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
499 /* BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
501 return (BTM_ILLEGAL_VALUE);
504 /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
505 p_inq->inqparms = *p_inqparms;
506 p_inq->per_min_delay = min_delay;
507 p_inq->per_max_delay = max_delay;
508 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
509 p_inq->p_inq_results_cb = p_results_cb;
511 p_inq->inq_active = (UINT8)((p_inqparms->mode == BTM_LIMITED_INQUIRY) ?
512 (BTM_LIMITED_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE) :
513 (BTM_GENERAL_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE));
515 /* If a filter is specified, then save it for later and clear the current filter.
516 The setting of the filter is done upon completion of clearing of the previous
519 if (p_inqparms->filter_cond_type != BTM_CLR_INQUIRY_FILTER) {
520 p_inq->state = BTM_INQ_CLR_FILT_STATE;
521 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
522 } else { /* The filter is not being used so simply clear it; the inquiry can start after this operation */
523 p_inq->state = BTM_INQ_SET_FILT_STATE;
526 /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
527 if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type, &p_inqparms->filter_cond)) != BTM_CMD_STARTED) {
528 /* If set filter command is not succesful reset the state */
529 p_inq->p_inq_results_cb = NULL;
530 p_inq->state = BTM_INQ_INACTIVE_STATE;
538 /*******************************************************************************
540 ** Function BTM_CancelPeriodicInquiry
542 ** Description This function cancels a periodic inquiry
545 ** BTM_NO_RESOURCES if could not allocate a message buffer
546 ** BTM_SUCCESS - if cancelling the periodic inquiry
547 ** BTM_WRONG_MODE if the device is not up.
549 *******************************************************************************/
550 tBTM_STATUS BTM_CancelPeriodicInquiry(void)
552 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
553 tBTM_STATUS status = BTM_SUCCESS;
554 BTM_TRACE_API ("BTM_CancelPeriodicInquiry called\n");
556 /*** Make sure the device is ready ***/
557 if (!BTM_IsDeviceUp()) {
558 return (BTM_WRONG_MODE);
561 /* Only cancel if one is active */
562 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
563 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
564 btm_cb.btm_inq_vars.p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
566 if (!btsnd_hcic_exit_per_inq ()) {
567 status = BTM_NO_RESOURCES;
570 /* If the event filter is in progress, mark it so that the processing of the return
571 event will be ignored */
572 if (p_inq->inqfilt_active) {
573 p_inq->pending_filt_complete_event++;
576 p_inq->inqfilt_active = FALSE;
577 p_inq->inq_counter++;
584 /*******************************************************************************
586 ** Function BTM_SetConnectability
588 ** Description This function is called to set the device into or out of
589 ** connectable mode. Discoverable mode means page scans enabled.
591 ** Returns BTM_SUCCESS if successful
592 ** BTM_ILLEGAL_VALUE if a bad parameter is detected
593 ** BTM_NO_RESOURCES if could not allocate a message buffer
594 ** BTM_WRONG_MODE if the device is not up.
596 *******************************************************************************/
597 tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 interval)
600 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
602 BTM_TRACE_API ("BTM_SetConnectability\n");
604 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
605 if (controller_get_interface()->supports_ble()) {
606 if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS) {
607 return BTM_NO_RESOURCES;
609 p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
610 p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
612 page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
615 /*** Check mode parameter ***/
616 if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE) {
617 return (BTM_ILLEGAL_VALUE);
620 /* Make sure the controller is active */
621 if (!controller_get_interface()->get_is_ready()) {
622 return (BTM_DEV_RESET);
625 /* If the window and/or interval is '0', set to default values */
627 window = BTM_DEFAULT_CONN_WINDOW;
631 interval = BTM_DEFAULT_CONN_INTERVAL;
634 BTM_TRACE_API ("BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, interval 0x%04x\n",
635 page_mode, window, interval);
637 /*** Check for valid window and interval parameters ***/
638 /*** Only check window and duration if mode is connectable ***/
639 if (page_mode == BTM_CONNECTABLE) {
640 /* window must be less than or equal to interval */
641 if (window < HCI_MIN_PAGESCAN_WINDOW ||
642 window > HCI_MAX_PAGESCAN_WINDOW ||
643 interval < HCI_MIN_PAGESCAN_INTERVAL ||
644 interval > HCI_MAX_PAGESCAN_INTERVAL ||
646 return (BTM_ILLEGAL_VALUE);
649 scan_mode |= HCI_PAGE_SCAN_ENABLED;
652 if ((window != p_inq->page_scan_window) ||
653 (interval != p_inq->page_scan_period)) {
654 p_inq->page_scan_window = window;
655 p_inq->page_scan_period = interval;
656 if (!btsnd_hcic_write_pagescan_cfg (interval, window)) {
657 return (BTM_NO_RESOURCES);
661 /* Keep the inquiry scan as previouosly set */
662 if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK) {
663 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
666 if (btsnd_hcic_write_scan_enable (scan_mode)) {
667 p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
668 p_inq->connectable_mode |= page_mode;
670 return (BTM_SUCCESS);
673 return (BTM_NO_RESOURCES);
677 /*******************************************************************************
679 ** Function BTM_ReadConnectability
681 ** Description This function is called to read the current discoverability
682 ** mode of the device.
683 ** Output Params p_window - current page scan duration
684 ** p_interval - current time between page scans
686 ** Returns BTM_NON_CONNECTABLE or BTM_CONNECTABLE
688 *******************************************************************************/
689 UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval)
691 BTM_TRACE_API ("BTM_ReadConnectability\n");
693 *p_window = btm_cb.btm_inq_vars.page_scan_window;
697 *p_interval = btm_cb.btm_inq_vars.page_scan_period;
700 return (btm_cb.btm_inq_vars.connectable_mode);
705 /*******************************************************************************
707 ** Function BTM_IsInquiryActive
709 ** Description This function returns a bit mask of the current inquiry state
711 ** Returns BTM_INQUIRY_INACTIVE if inactive (0)
712 ** BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active
713 ** BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active
714 ** BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active
716 *******************************************************************************/
717 UINT16 BTM_IsInquiryActive (void)
719 BTM_TRACE_API ("BTM_IsInquiryActive\n");
721 return (btm_cb.btm_inq_vars.inq_active);
726 /*******************************************************************************
728 ** Function BTM_CancelInquiry
730 ** Description This function cancels an inquiry if active
732 ** Returns BTM_SUCCESS if successful
733 ** BTM_NO_RESOURCES if could not allocate a message buffer
734 ** BTM_WRONG_MODE if the device is not up.
736 *******************************************************************************/
737 tBTM_STATUS BTM_CancelInquiry(void)
739 tBTM_STATUS status = BTM_SUCCESS;
740 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
741 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
742 UINT8 active_mode = p_inq->inq_active;
744 BTM_TRACE_API ("BTM_CancelInquiry called\n");
746 /*** Make sure the device is ready ***/
747 if (!BTM_IsDeviceUp()) {
748 return (BTM_WRONG_MODE);
751 /* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
752 if ((p_inq->inq_active & BTM_INQUIRY_ACTIVE_MASK) != 0 &&
753 (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))) {
754 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
755 p_inq->state = BTM_INQ_INACTIVE_STATE;
756 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; /* Do not notify caller anymore */
757 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL; /* Do not notify caller anymore */
759 /* If the event filter is in progress, mark it so that the processing of the return
760 event will be ignored */
761 if (p_inq->inqfilt_active) {
762 p_inq->inqfilt_active = FALSE;
763 p_inq->pending_filt_complete_event++;
765 /* Initiate the cancel inquiry */
767 if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
768 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
769 && (active_mode & BTM_BR_INQUIRY_MASK)
772 if (!btsnd_hcic_inq_cancel()) {
773 status = BTM_NO_RESOURCES;
776 #if BLE_INCLUDED == TRUE
777 if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
778 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
779 && (active_mode & BTM_BLE_INQ_ACTIVE_MASK)
782 btm_ble_stop_inquiry();
787 /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
788 * and then send the BUSY_LEVEL event
789 * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
792 p_inq->inq_counter++;
793 btm_clr_inq_result_flt();
800 /*******************************************************************************
802 ** Function BTM_StartInquiry
804 ** Description This function is called to start an inquiry.
806 ** Parameters: p_inqparms - pointer to the inquiry information
807 ** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
808 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
809 ** max_resps - maximum amount of devices to search for before ending the inquiry
810 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
811 ** BTM_FILTER_COND_BD_ADDR
812 ** filter_cond - value for the filter (based on filter_cond_type)
814 ** p_results_cb - Pointer to the callback routine which gets called
815 ** upon receipt of an inquiry result. If this field is
816 ** NULL, the application is not notified.
818 ** p_cmpl_cb - Pointer to the callback routine which gets called
819 ** upon completion. If this field is NULL, the
820 ** application is not notified when completed.
821 ** Returns tBTM_STATUS
822 ** BTM_CMD_STARTED if successfully initiated
823 ** BTM_BUSY if already in progress
824 ** BTM_ILLEGAL_VALUE if parameter(s) are out of range
825 ** BTM_NO_RESOURCES if could not allocate resources to start the command
826 ** BTM_WRONG_MODE if the device is not up.
828 *******************************************************************************/
829 tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
830 tBTM_CMPL_CB *p_cmpl_cb)
832 tBTM_STATUS status = BTM_CMD_STARTED;
833 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
835 BTM_TRACE_API ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d\n",
836 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
837 p_inqparms->filter_cond_type);
839 /* Only one active inquiry is allowed in this implementation.
840 Also do not allow an inquiry if the inquiry filter is being updated */
841 if (p_inq->inq_active || p_inq->inqfilt_active) {
842 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
843 /*check if LE observe is already running*/
844 if (p_inq->scan_type == INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb != NULL) {
845 BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
846 p_inq->scan_type = INQ_GENERAL;
847 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
848 btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
849 btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
854 BTM_TRACE_API("BTM_StartInquiry: return BUSY\n");
857 p_inq->scan_type = INQ_GENERAL;
860 /*** Make sure the device is ready ***/
861 if (!BTM_IsDeviceUp()) {
862 return (BTM_WRONG_MODE);
865 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
866 (p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY
867 #if (BLE_INCLUDED == TRUE)
868 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY
869 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY
872 return (BTM_ILLEGAL_VALUE);
875 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
876 if (p_inq->next_state == BTM_FINISH) {
877 return BTM_ILLEGAL_VALUE;
882 /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
883 p_inq->inqparms = *p_inqparms;
885 /* Initialize the inquiry variables */
886 p_inq->state = BTM_INQ_ACTIVE_STATE;
887 p_inq->p_inq_cmpl_cb = p_cmpl_cb;
888 p_inq->p_inq_results_cb = p_results_cb;
889 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
890 p_inq->inq_active = p_inqparms->mode;
892 BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x\n", p_inq->inq_active);
894 /* interleave scan minimal conditions */
895 #if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE))
897 /* check if both modes are present */
898 if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) && (p_inqparms->mode & BTM_BR_INQUIRY_MASK)) {
899 BTM_TRACE_API("BTM:Interleave Inquiry Mode Set\n");
900 p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state];
901 p_inq->inqparms.duration = p_inqparms->duration;
903 BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x\n", p_inqparms->mode);
904 p_inq->next_state = BTM_NO_INTERLEAVING;
910 /* start LE inquiry here if requested */
911 #if BLE_INCLUDED == TRUE
912 if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
913 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
914 && (p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO ||
915 p_inq->next_state == BTM_NO_INTERLEAVING)
920 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
921 p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
922 BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x\n",
923 p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
925 if (!controller_get_interface()->supports_ble()) {
926 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
927 status = BTM_ILLEGAL_VALUE;
929 /* BLE for now does not support filter condition for inquiry */
930 else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
931 p_inqparms->duration)) != BTM_CMD_STARTED) {
932 BTM_TRACE_ERROR("Err Starting LE Inquiry.\n");
933 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
935 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
936 p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
939 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
940 if (p_inq->next_state == BTM_NO_INTERLEAVING) {
941 p_inq->next_state = BTM_FINISH;
943 BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d\n",
944 p_inq->next_state + 1);
945 p_inq->next_state += 1;
947 /* reset next_state if status <> BTM_Started */
948 if (status != BTM_CMD_STARTED) {
949 p_inq->next_state = BTM_BR_ONE;
952 /* if interleave scan..return here */
957 BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x\n", p_inqparms->mode);
959 #endif /* end of BLE_INCLUDED */
961 /* we're done with this routine if BR/EDR inquiry is not desired. */
962 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE) {
966 /* BR/EDR inquiry portion */
967 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
968 if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO ||
969 p_inq->next_state == BTM_NO_INTERLEAVING )) {
970 p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
972 /* If a filter is specified, then save it for later and clear the current filter.
973 The setting of the filter is done upon completion of clearing of the previous
976 switch (p_inqparms->filter_cond_type) {
977 case BTM_CLR_INQUIRY_FILTER:
978 p_inq->state = BTM_INQ_SET_FILT_STATE;
981 case BTM_FILTER_COND_DEVICE_CLASS:
982 case BTM_FILTER_COND_BD_ADDR:
983 /* The filter is not being used so simply clear it;
984 the inquiry can start after this operation */
985 p_inq->state = BTM_INQ_CLR_FILT_STATE;
986 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
987 /* =============>>>> adding LE filtering here ????? */
991 return (BTM_ILLEGAL_VALUE);
994 /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
995 if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
996 &p_inqparms->filter_cond)) != BTM_CMD_STARTED) {
997 p_inq->state = BTM_INQ_INACTIVE_STATE;
1000 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
1001 if (p_inq->next_state == BTM_NO_INTERLEAVING) {
1002 p_inq->next_state = BTM_FINISH;
1004 BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d\n",
1005 p_inq->next_state + 1);
1006 p_inq->next_state += 1;
1009 if (status != BTM_CMD_STARTED) {
1010 /* Some error beginning the scan process.
1011 Reset the next_state parameter.. Do we need to reset the inq_active also?
1013 BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x\n", status);
1014 p_inq->next_state = BTM_BR_ONE;
1023 /*******************************************************************************
1025 ** Function BTM_ReadRemoteDeviceName
1027 ** Description This function initiates a remote device HCI command to the
1028 ** controller and calls the callback when the process has completed.
1030 ** Input Params: remote_bda - device address of name to retrieve
1031 ** p_cb - callback function called when BTM_CMD_STARTED
1033 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
1037 ** BTM_CMD_STARTED is returned if the request was successfully sent
1039 ** BTM_BUSY if already in progress
1040 ** BTM_UNKNOWN_ADDR if device address is bad
1041 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1042 ** BTM_WRONG_MODE if the device is not up.
1044 *******************************************************************************/
1045 tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
1046 , tBT_TRANSPORT transport)
1048 tBTM_INQ_INFO *p_cur = NULL;
1051 BTM_TRACE_API ("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]\n",
1052 remote_bda[0], remote_bda[1], remote_bda[2],
1053 remote_bda[3], remote_bda[4], remote_bda[5]);
1055 /* Use the remote device's clock offset if it is in the local inquiry database */
1056 if ((p_i = btm_inq_db_find (remote_bda)) != NULL) {
1057 p_cur = &p_i->inq_info;
1059 BTM_TRACE_API ("no device found in inquiry db\n");
1061 #if (BLE_INCLUDED == TRUE)
1062 if (transport == BT_TRANSPORT_LE) {
1063 return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
1067 return (btm_initiate_rem_name (remote_bda, p_cur, BTM_RMT_NAME_EXT,
1068 BTM_EXT_RMT_NAME_TIMEOUT, p_cb));
1071 /*******************************************************************************
1073 ** Function BTM_CancelRemoteDeviceName
1075 ** Description This function initiates the cancel request for the specified
1078 ** Input Params: None
1081 ** BTM_CMD_STARTED is returned if the request was successfully sent
1083 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1084 ** BTM_WRONG_MODE if there is not an active remote name request.
1086 *******************************************************************************/
1087 tBTM_STATUS BTM_CancelRemoteDeviceName (void)
1089 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1091 BTM_TRACE_API ("BTM_CancelRemoteDeviceName()\n");
1093 /* Make sure there is not already one in progress */
1094 if (p_inq->remname_active) {
1095 #if BLE_INCLUDED == TRUE
1096 if (BTM_UseLeLink(p_inq->remname_bda)) {
1097 if (btm_ble_cancel_remote_name(p_inq->remname_bda)) {
1098 return (BTM_CMD_STARTED);
1100 return (BTM_UNKNOWN_ADDR);
1104 if (btsnd_hcic_rmt_name_req_cancel (p_inq->remname_bda)) {
1105 return (BTM_CMD_STARTED);
1107 return (BTM_NO_RESOURCES);
1110 return (BTM_WRONG_MODE);
1114 /*******************************************************************************
1116 ** Function BTM_InqDbRead
1118 ** Description This function looks through the inquiry database for a match
1119 ** based on Bluetooth Device Address. This is the application's
1120 ** interface to get the inquiry details of a specific BD address.
1122 ** Returns pointer to entry, or NULL if not found
1124 *******************************************************************************/
1125 tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
1127 BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]\n",
1128 p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
1130 tINQ_DB_ENT *p_ent = btm_inq_db_find(p_bda);
1135 return &p_ent->inq_info;
1139 /*******************************************************************************
1141 ** Function BTM_InqDbFirst
1143 ** Description This function looks through the inquiry database for the first
1144 ** used entry, and returns that. This is used in conjunction with
1145 ** BTM_InqDbNext by applications as a way to walk through the
1146 ** inquiry database.
1148 ** Returns pointer to first in-use entry, or NULL if DB is empty
1150 *******************************************************************************/
1151 tBTM_INQ_INFO *BTM_InqDbFirst (void)
1154 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1156 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1157 if (p_ent->in_use) {
1158 return (&p_ent->inq_info);
1162 /* If here, no used entry found */
1163 return ((tBTM_INQ_INFO *)NULL);
1167 /*******************************************************************************
1169 ** Function BTM_InqDbNext
1171 ** Description This function looks through the inquiry database for the next
1172 ** used entry, and returns that. If the input parameter is NULL,
1173 ** the first entry is returned.
1175 ** Returns pointer to next in-use entry, or NULL if no more found.
1177 *******************************************************************************/
1178 tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur)
1184 p_ent = (tINQ_DB_ENT *) ((UINT8 *)p_cur - offsetof (tINQ_DB_ENT, inq_info));
1185 inx = (UINT16)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1187 for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++) {
1188 if (p_ent->in_use) {
1189 return (&p_ent->inq_info);
1193 /* If here, more entries found */
1194 return ((tBTM_INQ_INFO *)NULL);
1196 return (BTM_InqDbFirst());
1201 /*******************************************************************************
1203 ** Function BTM_ClearInqDb
1205 ** Description This function is called to clear out a device or all devices
1206 ** from the inquiry database.
1208 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1209 ** (NULL clears all entries)
1211 ** Returns BTM_BUSY if an inquiry, get remote name, or event filter
1212 ** is active, otherwise BTM_SUCCESS
1214 *******************************************************************************/
1215 tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda)
1217 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1219 /* If an inquiry or remote name is in progress return busy */
1220 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE ||
1221 p_inq->inqfilt_active) {
1225 btm_clr_inq_db(p_bda);
1227 return (BTM_SUCCESS);
1230 /*******************************************************************************
1232 ** Function BTM_ReadInquiryRspTxPower
1234 ** Description This command will read the inquiry Transmit Power level used
1235 ** to transmit the FHS and EIR data packets.
1236 ** This can be used directly in the Tx Power Level EIR data type.
1238 ** Returns BTM_SUCCESS if successful
1240 *******************************************************************************/
1241 tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb)
1243 if (btm_cb.devcb.p_txpwer_cmpl_cb) {
1247 btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT );
1250 btm_cb.devcb.p_txpwer_cmpl_cb = p_cb;
1252 if (!btsnd_hcic_read_inq_tx_power ()) {
1253 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
1254 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
1255 return (BTM_NO_RESOURCES);
1257 return (BTM_CMD_STARTED);
1261 /*********************************************************************************
1262 **********************************************************************************
1264 ** BTM Internal Inquiry Functions **
1266 **********************************************************************************
1267 *********************************************************************************/
1268 /*******************************************************************************
1270 ** Function btm_inq_db_reset
1272 ** Description This function is called at at reset to clear the inquiry
1273 ** database & pending callback.
1277 *******************************************************************************/
1278 void btm_inq_db_reset (void)
1280 tBTM_REMOTE_DEV_NAME rem_name;
1281 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1282 UINT8 num_responses;
1283 UINT8 temp_inq_active;
1286 btu_stop_timer (&p_inq->inq_timer_ent);
1288 /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
1289 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE) {
1290 temp_inq_active = p_inq->inq_active; /* Save so state can change BEFORE
1291 callback is called */
1292 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1294 /* If not a periodic inquiry, the complete callback must be called to notify caller */
1295 if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
1296 temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE) {
1297 if (p_inq->p_inq_cmpl_cb) {
1299 (*p_inq->p_inq_cmpl_cb)(&num_responses);
1304 /* Cancel a remote name request if active, and notify the caller (if waiting) */
1305 if (p_inq->remname_active ) {
1306 btu_stop_timer (&p_inq->rmt_name_timer_ent);
1307 p_inq->remname_active = FALSE;
1308 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
1310 if (p_inq->p_remname_cmpl_cb) {
1311 rem_name.status = BTM_DEV_RESET;
1313 (*p_inq->p_remname_cmpl_cb)(&rem_name);
1314 p_inq->p_remname_cmpl_cb = NULL;
1318 /* Cancel an inquiry filter request if active, and notify the caller (if waiting) */
1319 if (p_inq->inqfilt_active) {
1320 p_inq->inqfilt_active = FALSE;
1322 if (p_inq->p_inqfilter_cmpl_cb) {
1323 status = BTM_DEV_RESET;
1324 (*p_inq->p_inqfilter_cmpl_cb)(&status);
1328 p_inq->state = BTM_INQ_INACTIVE_STATE;
1329 p_inq->pending_filt_complete_event = 0;
1330 p_inq->p_inq_results_cb = NULL;
1331 btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
1332 btm_clr_inq_result_flt();
1334 p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1335 p_inq->connectable_mode = BTM_NON_CONNECTABLE;
1336 p_inq->page_scan_type = BTM_SCAN_TYPE_STANDARD;
1337 p_inq->inq_scan_type = BTM_SCAN_TYPE_STANDARD;
1339 #if BLE_INCLUDED == TRUE
1340 p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1341 p_inq->connectable_mode |= BTM_BLE_NON_CONNECTABLE;
1347 /*********************************************************************************
1349 ** Function btm_inq_db_init
1351 ** Description This function is called at startup to initialize the inquiry
1356 *******************************************************************************/
1357 void btm_inq_db_init (void)
1359 #if 0 /* cleared in btm_init; put back in if called from anywhere else! */
1360 memset (&btm_cb.btm_inq_vars, 0, sizeof (tBTM_INQUIRY_VAR_ST));
1363 btu_free_timer(&btm_cb.btm_inq_vars.rmt_name_timer_ent);
1364 memset(&btm_cb.btm_inq_vars.rmt_name_timer_ent, 0, sizeof(TIMER_LIST_ENT));
1365 btu_free_timer(&btm_cb.btm_inq_vars.inq_timer_ent);
1366 memset(&btm_cb.btm_inq_vars.inq_timer_ent, 0, sizeof(TIMER_LIST_ENT));
1368 btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1371 /*********************************************************************************
1373 ** Function btm_inq_stop_on_ssp
1375 ** Description This function is called on incoming SSP
1379 *******************************************************************************/
1380 void btm_inq_stop_on_ssp(void)
1382 UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1384 #if (BTM_INQ_DEBUG == TRUE)
1385 BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d\n",
1386 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);
1388 if (btm_cb.btm_inq_vars.no_inc_ssp) {
1389 if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1390 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1391 BTM_CancelPeriodicInquiry();
1392 } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1393 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1394 btsnd_hcic_inq_cancel();
1397 /* do not allow inquiry to start */
1398 btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1402 /*********************************************************************************
1404 ** Function btm_inq_clear_ssp
1406 ** Description This function is called when pairing_state becomes idle
1410 *******************************************************************************/
1411 void btm_inq_clear_ssp(void)
1413 btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1416 /*********************************************************************************
1418 ** Function btm_clr_inq_db
1420 ** Description This function is called to clear out a device or all devices
1421 ** from the inquiry database.
1423 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1424 ** (NULL clears all entries)
1428 *******************************************************************************/
1429 void btm_clr_inq_db (BD_ADDR p_bda)
1431 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1432 tINQ_DB_ENT *p_ent = p_inq->inq_db;
1435 #if (BTM_INQ_DEBUG == TRUE)
1436 BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d\n",
1437 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1439 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1440 if (p_ent->in_use) {
1441 /* If this is the specified BD_ADDR or clearing all devices */
1442 if (p_bda == NULL ||
1443 (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1444 p_ent->in_use = FALSE;
1448 #if (BTM_INQ_DEBUG == TRUE)
1449 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d\n",
1450 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1455 /*******************************************************************************
1457 ** Function btm_clr_inq_result_flt
1459 ** Description This function looks through the bdaddr database for a match
1460 ** based on Bluetooth Device Address
1462 ** Returns TRUE if found, else FALSE (new entry)
1464 *******************************************************************************/
1465 static void btm_clr_inq_result_flt (void)
1467 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1469 if (p_inq->p_bd_db) {
1470 osi_free(p_inq->p_bd_db);
1471 p_inq->p_bd_db = NULL;
1473 p_inq->num_bd_entries = 0;
1474 p_inq->max_bd_entries = 0;
1477 /*******************************************************************************
1479 ** Function btm_inq_find_bdaddr
1481 ** Description This function looks through the bdaddr database for a match
1482 ** based on Bluetooth Device Address
1484 ** Returns TRUE if found, else FALSE (new entry)
1486 *******************************************************************************/
1487 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1489 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1490 tINQ_BDADDR *p_db = &p_inq->p_bd_db[0];
1493 /* Don't bother searching, database doesn't exist or periodic mode */
1494 if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db) {
1498 for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1499 if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1500 && p_db->inq_count == p_inq->inq_counter) {
1505 if (xx < p_inq->max_bd_entries) {
1506 p_db->inq_count = p_inq->inq_counter;
1507 memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1508 p_inq->num_bd_entries++;
1511 /* If here, New Entry */
1515 /*******************************************************************************
1517 ** Function btm_inq_db_find
1519 ** Description This function looks through the inquiry database for a match
1520 ** based on Bluetooth Device Address
1522 ** Returns pointer to entry, or NULL if not found
1524 *******************************************************************************/
1525 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1528 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1530 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1531 if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1536 /* If here, not found */
1541 /*******************************************************************************
1543 ** Function btm_inq_db_new
1545 ** Description This function looks through the inquiry database for an unused
1546 ** entry. If no entry is free, it allocates the oldest entry.
1548 ** Returns pointer to entry
1550 *******************************************************************************/
1551 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1554 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1555 tINQ_DB_ENT *p_old = btm_cb.btm_inq_vars.inq_db;
1556 UINT32 ot = 0xFFFFFFFF;
1558 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1559 if (!p_ent->in_use) {
1560 memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1561 memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1562 p_ent->in_use = TRUE;
1567 if (p_ent->time_of_resp < ot) {
1569 ot = p_ent->time_of_resp;
1573 /* If here, no free entry found. Return the oldest. */
1575 memset (p_old, 0, sizeof (tINQ_DB_ENT));
1576 memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1577 p_old->in_use = TRUE;
1583 /*******************************************************************************
1585 ** Function btm_set_inq_event_filter
1587 ** Description This function is called to set the inquiry event filter.
1588 ** It is called by either internally, or by the external API function
1589 ** (BTM_SetInqEventFilter). It is used internally as part of the
1590 ** inquiry processing.
1593 ** filter_cond_type - this is the type of inquiry filter to apply:
1594 ** BTM_FILTER_COND_DEVICE_CLASS,
1595 ** BTM_FILTER_COND_BD_ADDR, or
1596 ** BTM_CLR_INQUIRY_FILTER
1598 ** p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1599 ** filter_cond_type (See section 4.7.3 of Core Spec 1.0b).
1601 ** Returns BTM_CMD_STARTED if successfully initiated
1602 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
1603 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
1605 *******************************************************************************/
1606 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1607 tBTM_INQ_FILT_COND *p_filt_cond)
1609 UINT8 condition_length = DEV_CLASS_LEN * 2;
1610 UINT8 condition_buf[DEV_CLASS_LEN * 2];
1611 UINT8 *p_cond = condition_buf; /* points to the condition to pass to HCI */
1613 #if (BTM_INQ_DEBUG == TRUE)
1614 BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]\n",
1616 BTM_TRACE_DEBUG (" condition [%02x%02x%02x %02x%02x%02x]\n",
1617 p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1618 p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1621 /* Load the correct filter condition to pass to the lower layer */
1622 switch (filter_cond_type) {
1623 case BTM_FILTER_COND_DEVICE_CLASS:
1624 /* copy the device class and device class fields into contiguous memory to send to HCI */
1625 memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1626 memcpy (&condition_buf[DEV_CLASS_LEN],
1627 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1629 /* condition length should already be set as the default */
1632 case BTM_FILTER_COND_BD_ADDR:
1633 p_cond = p_filt_cond->bdaddr_cond;
1635 /* condition length should already be set as the default */
1638 case BTM_CLR_INQUIRY_FILTER:
1639 condition_length = 0;
1643 return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1646 btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1648 /* Filter the inquiry results for the specified condition type and value */
1649 if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1650 p_cond, condition_length))
1653 return (BTM_CMD_STARTED);
1655 return (BTM_NO_RESOURCES);
1660 /*******************************************************************************
1662 ** Function btm_event_filter_complete
1664 ** Description This function is called when a set event filter has completed.
1665 ** Note: This routine currently only handles inquiry filters.
1666 ** Connection filters are ignored for now.
1670 *******************************************************************************/
1671 void btm_event_filter_complete (UINT8 *p)
1675 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1676 tBTM_CMPL_CB *p_cb = p_inq->p_inqfilter_cmpl_cb;
1678 #if (BTM_INQ_DEBUG == TRUE)
1679 BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d\n",
1680 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1682 /* If the filter complete event is from an old or cancelled request, ignore it */
1683 if (p_inq->pending_filt_complete_event) {
1684 p_inq->pending_filt_complete_event--;
1688 /* Only process the inquiry filter; Ignore the connection filter until it
1689 is used by the upper layers */
1690 if (p_inq->inqfilt_active == TRUE ) {
1691 /* Extract the returned status from the buffer */
1692 STREAM_TO_UINT8 (hci_status, p);
1693 if (hci_status != HCI_SUCCESS) {
1694 /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1695 BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)\n", hci_status);
1696 status = BTM_ERR_PROCESSING;
1698 status = BTM_SUCCESS;
1701 /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1702 callback function to notify the initiator that it has completed */
1703 if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1704 p_inq->inqfilt_active = FALSE;
1708 } else /* An inquiry is active (the set filter command was internally generated),
1709 process the next state of the process (Set a new filter or start the inquiry). */
1711 if (status != BTM_SUCCESS) {
1712 /* Process the inquiry complete (Error Status) */
1713 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1715 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1716 p_inq->inqfilt_active = FALSE;
1717 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1718 p_inq->state = BTM_INQ_INACTIVE_STATE;
1723 /* Check to see if a new filter needs to be set up */
1724 if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1725 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED) {
1726 p_inq->state = BTM_INQ_SET_FILT_STATE;
1727 } else { /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1728 p_inq->inqfilt_active = FALSE;
1730 /* Process the inquiry complete (Error Status) */
1731 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1733 } else { /* Initiate the Inquiry or Periodic Inquiry */
1734 p_inq->state = BTM_INQ_ACTIVE_STATE;
1735 p_inq->inqfilt_active = FALSE;
1736 btm_initiate_inquiry (p_inq);
1743 /*******************************************************************************
1745 ** Function btm_initiate_inquiry
1747 ** Description This function is called to start an inquiry or periodic inquiry
1748 ** upon completion of the setting and/or clearing of the inquiry filter.
1750 ** Inputs: p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1751 ** mode - GENERAL or LIMITED inquiry
1752 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1753 ** max_resps - maximum amount of devices to search for before ending the inquiry
1754 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1755 ** BTM_FILTER_COND_BD_ADDR
1756 ** filter_cond - value for the filter (based on filter_cond_type)
1758 ** Returns If an error occurs the initiator's callback is called with the error status.
1760 *******************************************************************************/
1761 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1764 tBTM_INQ_PARMS *p_inqparms = &p_inq->inqparms;
1766 #if (BTM_INQ_DEBUG == TRUE)
1767 BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d\n",
1768 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1770 btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1772 if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1773 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1777 /* Make sure the number of responses doesn't overflow the database configuration */
1778 p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1780 lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1782 if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1783 if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1784 p_inq->per_min_delay,
1785 *lap, p_inqparms->duration,
1786 p_inqparms->max_resps)) {
1787 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1790 btm_clr_inq_result_flt();
1792 /* Allocate memory to hold bd_addrs responding */
1793 if ((p_inq->p_bd_db = (tINQ_BDADDR *)osi_calloc(BT_DEFAULT_BUFFER_SIZE)) != NULL) {
1794 p_inq->max_bd_entries = (UINT16)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1795 /* BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1796 p_inq->max_bd_entries); */
1799 if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0)) {
1800 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1805 /*******************************************************************************
1807 ** Function btm_process_inq_results
1809 ** Description This function is called when inquiry results are received from
1810 ** the device. It updates the inquiry database. If the inquiry
1811 ** database is full, the oldest entry is discarded.
1813 ** Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
1814 ** BTM_INQ_RESULT_WITH_RSSI
1815 ** BTM_INQ_RESULT_EXTENDED
1819 *******************************************************************************/
1820 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1825 tBTM_INQ_RESULTS *p_cur = NULL;
1826 BOOLEAN is_new = TRUE;
1827 BOOLEAN update = FALSE;
1829 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1830 tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1831 UINT8 page_scan_rep_mode = 0;
1832 UINT8 page_scan_per_mode = 0;
1833 UINT8 page_scan_mode = 0;
1836 UINT16 clock_offset;
1837 UINT8 *p_eir_data = NULL;
1839 #if (BTM_INQ_DEBUG == TRUE)
1840 BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d inq_res_mode=%d\n",
1841 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active, inq_res_mode);
1843 /* Only process the results if the BR inquiry is still active */
1844 if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) {
1848 STREAM_TO_UINT8 (num_resp, p);
1850 for (xx = 0; xx < num_resp; xx++) {
1852 /* Extract inquiry results */
1853 STREAM_TO_BDADDR (bda, p);
1854 STREAM_TO_UINT8 (page_scan_rep_mode, p);
1855 STREAM_TO_UINT8 (page_scan_per_mode, p);
1857 if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1858 STREAM_TO_UINT8(page_scan_mode, p);
1861 STREAM_TO_DEVCLASS (dc, p);
1862 STREAM_TO_UINT16 (clock_offset, p);
1863 if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1864 STREAM_TO_UINT8(rssi, p);
1867 p_i = btm_inq_db_find (bda);
1869 /* Only process the num_resp is smaller than max_resps.
1870 If results are queued to BTU task while canceling inquiry,
1871 or when more than one result is in this response, > max_resp
1872 responses could be processed which can confuse some apps
1874 if (p_inq->inqparms.max_resps &&
1875 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1876 #if BLE_INCLUDED == TRUE
1877 /* new device response */
1879 /* exisiting device with BR/EDR info */
1880 (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1885 BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring\n");
1889 /* Check if this address has already been processed for this inquiry */
1890 if (btm_inq_find_bdaddr(bda)) {
1891 BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]\n",
1892 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
1893 /* By default suppose no update needed */
1894 i_rssi = (INT8)rssi;
1896 /* If this new RSSI is higher than the last one */
1897 if (p_inq->inqparms.report_dup && (rssi != 0) &&
1898 p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1899 #if BLE_INCLUDED == TRUE
1900 /* BR/EDR inquiry information update */
1901 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1904 p_cur = &p_i->inq_info.results;
1905 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d\n", i_rssi, p_cur->rssi);
1906 p_cur->rssi = i_rssi;
1909 /* If we received a second Extended Inq Event for an already */
1910 /* discovered device, this is because for the first one EIR was not received */
1911 else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1912 p_cur = &p_i->inq_info.results;
1915 /* If no update needed continue with next response (if any) */
1921 /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
1923 p_i = btm_inq_db_new (bda);
1927 /* If an entry for the device already exists, overwrite it ONLY if it is from
1928 a previous inquiry. (Ignore it if it is a duplicate response from the same
1931 else if (p_i->inq_count == p_inq->inq_counter
1932 #if (BLE_INCLUDED == TRUE )
1933 && (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)
1939 /* keep updating RSSI to have latest value */
1940 if ( inq_res_mode != BTM_INQ_RESULT_STANDARD ) {
1941 p_i->inq_info.results.rssi = (INT8)rssi;
1943 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1946 if (is_new == TRUE) {
1948 p_cur = &p_i->inq_info.results;
1949 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1950 p_cur->page_scan_per_mode = page_scan_per_mode;
1951 p_cur->page_scan_mode = page_scan_mode;
1952 p_cur->dev_class[0] = dc[0];
1953 p_cur->dev_class[1] = dc[1];
1954 p_cur->dev_class[2] = dc[2];
1955 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1957 p_i->time_of_resp = osi_time_get_os_boottime_ms();
1959 if (p_i->inq_count != p_inq->inq_counter) {
1960 p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
1963 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
1964 p_cur->inq_result_type = BTM_INQ_RESULT_BR;
1965 if (p_i->inq_count != p_inq->inq_counter) {
1966 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1967 p_i->scan_rsp = FALSE;
1969 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1972 p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
1974 /* If the number of responses found and not unlimited, issue a cancel inquiry */
1975 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1976 p_inq->inqparms.max_resps &&
1977 p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
1978 #if BLE_INCLUDED == TRUE
1979 /* BLE scanning is active and received adv */
1980 && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1981 p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1982 (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
1985 /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
1986 btsnd_hcic_inq_cancel();
1988 #if BLE_INCLUDED == TRUE
1989 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) {
1990 btm_ble_stop_inquiry();
1993 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
1995 /* Initialize flag to FALSE. This flag is set/used by application */
1996 p_i->inq_info.appl_knows_rem_name = FALSE;
1999 if (is_new || update) {
2000 if ( inq_res_mode == BTM_INQ_RESULT_EXTENDED ) {
2001 memset( p_cur->eir_uuid, 0,
2002 BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
2003 /* set bit map of UUID list from received EIR */
2004 btm_set_eir_uuid( p, p_cur );
2010 /* If a callback is registered, call it with the results */
2011 if (p_inq_results_cb) {
2012 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2018 /*******************************************************************************
2020 ** Function btm_sort_inq_result
2022 ** Description This function is called when inquiry complete is received
2023 ** from the device to sort inquiry results based on rssi.
2027 *******************************************************************************/
2028 void btm_sort_inq_result(void)
2030 UINT8 xx, yy, num_resp;
2031 tINQ_DB_ENT *p_tmp = NULL;
2032 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
2033 tINQ_DB_ENT *p_next = btm_cb.btm_inq_vars.inq_db + 1;
2036 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE) ?
2037 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp : BTM_INQ_DB_SIZE;
2039 if ((p_tmp = (tINQ_DB_ENT *)osi_malloc(sizeof(tINQ_DB_ENT))) != NULL) {
2040 size = sizeof(tINQ_DB_ENT);
2041 for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
2042 for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
2043 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
2044 memcpy (p_tmp, p_next, size);
2045 memcpy (p_next, p_ent, size);
2046 memcpy (p_ent, p_tmp, size);
2055 /*******************************************************************************
2057 ** Function btm_process_inq_complete
2059 ** Description This function is called when inquiry complete is received
2060 ** from the device. Call the callback if not in periodic inquiry
2061 ** mode AND it is not NULL (The caller wants the event).
2063 ** The callback pass back the status and the number of responses
2067 *******************************************************************************/
2068 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2070 tBTM_CMPL_CB *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2071 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2073 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2074 /* inquiry inactive case happens when inquiry is cancelled.
2075 Make mode 0 for no further inquiries from the current inquiry process
2077 if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH || !p_inq->inq_active) {
2078 /* re-initialize for next inquiry request */
2079 p_inq->next_state = BTM_BR_ONE;
2080 /* make the mode 0 here */
2081 p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2086 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2087 p_inq->inqparms.mode &= ~(mode);
2090 if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
2091 /*end of LE observe*/
2092 p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2093 p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2094 p_inq->scan_type = INQ_NONE;
2098 #if (BTM_INQ_DEBUG == TRUE)
2099 BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d\n",
2100 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2102 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2103 /* Ignore any stray or late complete messages if the inquiry is not active */
2104 if (p_inq->inq_active) {
2105 p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2107 /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2108 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0) {
2109 #if BLE_INCLUDED == TRUE
2110 btm_clear_all_pending_le_entry();
2112 p_inq->state = BTM_INQ_INACTIVE_STATE;
2114 /* Increment so the start of a next inquiry has a new count */
2115 p_inq->inq_counter++;
2117 btm_clr_inq_result_flt();
2119 if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2120 controller_get_interface()->supports_rssi_with_inquiry_results()) {
2121 btm_sort_inq_result();
2124 /* Clear the results callback if set */
2125 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2126 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2127 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2129 /* If we have a callback registered for inquiry complete, call it */
2130 BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d\n",
2131 p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2134 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2137 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2138 if (p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
2139 /* make inquiry inactive for next iteration */
2140 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2141 /* call the inquiry again */
2142 BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb, p_inq->p_inq_cmpl_cb);
2146 if (p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL) { //this inquiry is complete
2147 p_inq->scan_type = INQ_NONE;
2148 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2149 /* check if the LE observe is pending */
2150 if (p_inq->p_inq_ble_results_cb != NULL) {
2151 BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2152 BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2156 #if (BTM_INQ_DEBUG == TRUE)
2157 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d\n",
2158 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2162 /*******************************************************************************
2164 ** Function btm_process_cancel_complete
2166 ** Description This function is called when inquiry cancel complete is received
2167 ** from the device.This function will also call the btm_process_inq_complete
2168 ** This function is needed to differentiate a cancel_cmpl_evt from the
2173 *******************************************************************************/
2174 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2176 btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2177 btm_process_inq_complete(status, mode);
2179 /*******************************************************************************
2181 ** Function btm_initiate_rem_name
2183 ** Description This function looks initiates a remote name request. It is called
2184 ** either by GAP or by the API call BTM_ReadRemoteDeviceName.
2186 ** Input Params: p_cur - pointer to an inquiry result structure (NULL if nonexistent)
2187 ** p_cb - callback function called when BTM_CMD_STARTED
2189 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2193 ** BTM_CMD_STARTED is returned if the request was sent to HCI.
2194 ** BTM_BUSY if already in progress
2195 ** BTM_NO_RESOURCES if could not allocate resources to start the command
2196 ** BTM_WRONG_MODE if the device is not up.
2198 *******************************************************************************/
2199 tBTM_STATUS btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2200 UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2202 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2206 /*** Make sure the device is ready ***/
2207 if (!BTM_IsDeviceUp()) {
2208 return (BTM_WRONG_MODE);
2212 if (origin == BTM_RMT_NAME_SEC) {
2213 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2214 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2216 return BTM_CMD_STARTED;
2218 return BTM_NO_RESOURCES;
2221 /* Make sure there are no two remote name requests from external API in progress */
2222 else if (origin == BTM_RMT_NAME_EXT) {
2223 if (p_inq->remname_active) {
2226 /* If there is no remote name request running,call the callback function and start timer */
2227 p_inq->p_remname_cmpl_cb = p_cb;
2228 memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2229 btu_start_timer (&p_inq->rmt_name_timer_ent,
2230 BTU_TTYPE_BTM_RMT_NAME,
2233 /* If the database entry exists for the device, use its clock offset */
2235 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2236 p_cur->results.page_scan_rep_mode,
2237 p_cur->results.page_scan_mode,
2238 (UINT16)(p_cur->results.clock_offset |
2239 BTM_CLOCK_OFFSET_VALID));
2240 } else { /* Otherwise use defaults and mark the clock offset as invalid */
2241 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2242 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2245 p_inq->remname_active = TRUE;
2246 return BTM_CMD_STARTED;
2248 return BTM_NO_RESOURCES;
2252 return BTM_ILLEGAL_VALUE;
2256 /*******************************************************************************
2258 ** Function btm_process_remote_name
2260 ** Description This function is called when a remote name is received from
2261 ** the device. If remote names are cached, it updates the inquiry
2266 *******************************************************************************/
2267 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2269 tBTM_REMOTE_DEV_NAME rem_name;
2270 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2271 tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
2274 UINT16 temp_evt_len;
2277 BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x\n", bda[0], bda[1],
2282 BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x\n", p_inq->remname_bda[0], p_inq->remname_bda[1],
2283 p_inq->remname_bda[2], p_inq->remname_bda[3],
2284 p_inq->remname_bda[4], p_inq->remname_bda[5]);
2288 /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2289 if ((p_inq->remname_active == TRUE) &&
2291 (memcmp(bda, p_inq->remname_bda, BD_ADDR_LEN) == 0)) || bda == NULL))
2294 #if BLE_INCLUDED == TRUE
2295 if (BTM_UseLeLink(p_inq->remname_bda)) {
2296 if (hci_status == HCI_ERR_UNSPECIFIED) {
2297 btm_ble_cancel_remote_name(p_inq->remname_bda);
2301 btu_stop_timer (&p_inq->rmt_name_timer_ent);
2302 p_inq->remname_active = FALSE;
2303 /* Clean up and return the status if the command was not successful */
2304 /* Note: If part of the inquiry, the name is not stored, and the */
2305 /* inquiry complete callback is called. */
2307 if (hci_status == HCI_SUCCESS) {
2308 /* Copy the name from the data stream into the return structure */
2309 /* Note that even if it is not being returned, it is used as a */
2310 /* temporary buffer. */
2311 p_n1 = (UINT8 *)rem_name.remote_bd_name;
2312 rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2313 rem_name.remote_bd_name[rem_name.length] = 0;
2314 rem_name.status = BTM_SUCCESS;
2315 temp_evt_len = rem_name.length;
2317 while (temp_evt_len > 0) {
2321 rem_name.remote_bd_name[rem_name.length] = 0;
2325 /* If processing a stand alone remote name then report the error in the callback */
2327 rem_name.status = BTM_BAD_VALUE_RET;
2328 rem_name.length = 0;
2329 rem_name.remote_bd_name[0] = 0;
2331 /* Reset the remote BAD to zero and call callback if possible */
2332 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2334 p_inq->p_remname_cmpl_cb = NULL;
2336 (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2341 /*******************************************************************************
2343 ** Function btm_inq_rmt_name_failed
2345 ** Description This function is if timeout expires while getting remote
2346 ** name. This is done for devices that incorrectly do not
2347 ** report operation failure
2351 *******************************************************************************/
2352 void btm_inq_rmt_name_failed (void)
2354 BTM_TRACE_ERROR ("btm_inq_rmt_name_failed() remname_active=%d\n", btm_cb.btm_inq_vars.remname_active);
2356 if (btm_cb.btm_inq_vars.remname_active) {
2357 btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2359 btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2361 #if (SMP_INCLUDED == TRUE)
2362 btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2363 #endif ///SMP_INCLUDED == TRUE
2365 /*******************************************************************************
2367 ** Function btm_read_linq_tx_power_complete
2369 ** Description read inquiry tx power level complete callback function.
2373 *******************************************************************************/
2374 void btm_read_linq_tx_power_complete(UINT8 *p)
2376 tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2377 tBTM_INQ_TXPWR_RESULTS results;
2379 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2380 /* If there was a callback registered for read inq tx power, call it */
2381 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2384 STREAM_TO_UINT8 (results.hci_status, p);
2386 if (results.hci_status == HCI_SUCCESS) {
2387 results.status = BTM_SUCCESS;
2389 STREAM_TO_UINT8 (results.tx_power, p);
2390 BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n",
2391 results.tx_power, results.hci_status);
2393 results.status = BTM_ERR_PROCESSING;
2400 /*******************************************************************************
2402 ** Function BTM_WriteEIR
2404 ** Description This function is called to write EIR data to controller.
2406 ** Parameters p_buff - allocated HCI command buffer including extended
2407 ** inquriry response
2409 ** Returns BTM_SUCCESS - if successful
2410 ** BTM_MODE_UNSUPPORTED - if local device cannot support it
2412 *******************************************************************************/
2413 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2415 if (controller_get_interface()->supports_extended_inquiry_response()) {
2416 BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
2417 btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2421 return BTM_MODE_UNSUPPORTED;
2425 /*******************************************************************************
2427 ** Function BTM_CheckEirData
2429 ** Description This function is called to get EIR data from significant part.
2431 ** Parameters p_eir - pointer of EIR significant part
2432 ** type - finding EIR data type
2433 ** p_length - return the length of EIR data not including type
2435 ** Returns pointer of EIR data
2437 *******************************************************************************/
2438 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2443 BTM_TRACE_API("BTM_CheckEirData type=0x%02X\n", type);
2445 STREAM_TO_UINT8(length, p);
2446 while ( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN)) {
2447 STREAM_TO_UINT8(eir_type, p);
2448 if ( eir_type == type ) {
2449 /* length doesn't include itself */
2450 *p_length = length - 1; /* minus the length of type */
2453 p += length - 1; /* skip the length of data */
2454 STREAM_TO_UINT8(length, p);
2461 /*******************************************************************************
2463 ** Function btm_convert_uuid_to_eir_service
2465 ** Description This function is called to get the bit position of UUID.
2467 ** Parameters uuid16 - UUID 16-bit
2469 ** Returns BTM EIR service ID if found
2470 ** BTM_EIR_MAX_SERVICES - if not found
2472 *******************************************************************************/
2473 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2477 for ( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ ) {
2478 if ( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
2482 return BTM_EIR_MAX_SERVICES;
2485 /*******************************************************************************
2487 ** Function BTM_HasEirService
2489 ** Description This function is called to know if UUID in bit map of UUID.
2491 ** Parameters p_eir_uuid - bit map of UUID list
2492 ** uuid16 - UUID 16-bit
2494 ** Returns TRUE - if found
2495 ** FALSE - if not found
2497 *******************************************************************************/
2498 BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2502 service_id = btm_convert_uuid_to_eir_service(uuid16);
2503 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2504 return ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2510 /*******************************************************************************
2512 ** Function BTM_HasInquiryEirService
2514 ** Description This function is called to know if UUID in bit map of UUID list.
2516 ** Parameters p_results - inquiry results
2517 ** uuid16 - UUID 16-bit
2519 ** Returns BTM_EIR_FOUND - if found
2520 ** BTM_EIR_NOT_FOUND - if not found and it is complete list
2521 ** BTM_EIR_UNKNOWN - if not found and it is not complete list
2523 *******************************************************************************/
2524 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2526 if ( BTM_HasEirService( p_results->eir_uuid, uuid16 )) {
2527 return BTM_EIR_FOUND;
2528 } else if ( p_results->eir_complete_list ) {
2529 return BTM_EIR_NOT_FOUND;
2531 return BTM_EIR_UNKNOWN;
2535 /*******************************************************************************
2537 ** Function BTM_AddEirService
2539 ** Description This function is called to add a service in bit map of UUID list.
2541 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2542 ** uuid16 - UUID 16-bit
2546 *******************************************************************************/
2547 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2551 service_id = btm_convert_uuid_to_eir_service(uuid16);
2552 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2553 BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2557 /*******************************************************************************
2559 ** Function BTM_RemoveEirService
2561 ** Description This function is called to remove a service in bit map of UUID list.
2563 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2564 ** uuid16 - UUID 16-bit
2568 *******************************************************************************/
2569 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2573 service_id = btm_convert_uuid_to_eir_service(uuid16);
2574 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2575 BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2579 /*******************************************************************************
2581 ** Function BTM_GetEirSupportedServices
2583 ** Description This function is called to get UUID list from bit map of UUID list.
2585 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2586 ** p - reference of current pointer of EIR
2587 ** max_num_uuid16 - max number of UUID can be written in EIR
2588 ** num_uuid16 - number of UUID have been written in EIR
2590 ** Returns BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2591 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2593 *******************************************************************************/
2594 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid, UINT8 **p,
2595 UINT8 max_num_uuid16, UINT8 *p_num_uuid16)
2597 UINT8 service_index;
2601 for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++) {
2602 if ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index )) {
2603 if ( *p_num_uuid16 < max_num_uuid16 ) {
2604 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2607 /* if max number of UUIDs are stored and found one more */
2609 return BTM_EIR_MORE_16BITS_UUID_TYPE;
2613 return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2616 /*******************************************************************************
2618 ** Function BTM_GetEirUuidList
2620 ** Description This function parses EIR and returns UUID list.
2622 ** Parameters p_eir - EIR
2623 ** uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2624 ** p_num_uuid - return number of UUID in found list
2625 ** p_uuid_list - return UUID list
2626 ** max_num_uuid - maximum number of UUID to be returned
2628 ** Returns 0 - if not found
2629 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2630 ** BTM_EIR_MORE_16BITS_UUID_TYPE
2631 ** BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2632 ** BTM_EIR_MORE_32BITS_UUID_TYPE
2633 ** BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2634 ** BTM_EIR_MORE_128BITS_UUID_TYPE
2636 *******************************************************************************/
2637 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2638 UINT8 *p_uuid_list, UINT8 max_num_uuid)
2643 UINT16 *p_uuid16 = (UINT16 *)p_uuid_list;
2644 UINT32 *p_uuid32 = (UINT32 *)p_uuid_list;
2645 char buff[LEN_UUID_128 * 2 + 1];
2647 p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2648 if ( p_uuid_data == NULL ) {
2652 if ( *p_num_uuid > max_num_uuid ) {
2653 BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d\n",
2654 *p_num_uuid, max_num_uuid );
2655 *p_num_uuid = max_num_uuid;
2658 BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d\n", type, *p_num_uuid );
2660 if ( uuid_size == LEN_UUID_16 ) {
2661 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2662 STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2663 BTM_TRACE_DEBUG(" 0x%04X\n", *(p_uuid16 + yy));
2665 } else if ( uuid_size == LEN_UUID_32 ) {
2666 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2667 STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2668 BTM_TRACE_DEBUG(" 0x%08X\n", *(p_uuid32 + yy));
2670 } else if ( uuid_size == LEN_UUID_128 ) {
2671 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2672 STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2673 for ( xx = 0; xx < LEN_UUID_128; xx++ ) {
2674 sprintf(buff + xx * 2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2676 BTM_TRACE_DEBUG(" 0x%s\n", buff);
2684 /*******************************************************************************
2686 ** Function btm_eir_get_uuid_list
2688 ** Description This function searches UUID list in EIR.
2690 ** Parameters p_eir - address of EIR
2691 ** uuid_size - size of UUID to find
2692 ** p_num_uuid - number of UUIDs found
2693 ** p_uuid_list_type - EIR data type
2695 ** Returns NULL - if UUID list with uuid_size is not found
2696 ** beginning of UUID list in EIR - otherwise
2698 *******************************************************************************/
2699 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2700 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2703 UINT8 complete_type, more_type;
2706 switch ( uuid_size ) {
2708 complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2709 more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2712 complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2713 more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
2716 complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2717 more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
2725 p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2726 if (p_uuid_data == NULL) {
2727 p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2728 *p_uuid_list_type = more_type;
2730 *p_uuid_list_type = complete_type;
2733 *p_num_uuid = uuid_len / uuid_size;
2737 /*******************************************************************************
2739 ** Function btm_convert_uuid_to_uuid16
2741 ** Description This function converts UUID to UUID 16-bit.
2743 ** Parameters p_uuid - address of UUID
2744 ** uuid_size - size of UUID
2746 ** Returns 0 - if UUID cannot be converted to UUID 16-bit
2747 ** UUID 16-bit - otherwise
2749 *******************************************************************************/
2750 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2752 static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2753 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2757 BOOLEAN is_base_uuid;
2760 switch (uuid_size) {
2762 STREAM_TO_UINT16 (uuid16, p_uuid);
2765 STREAM_TO_UINT32 (uuid32, p_uuid);
2766 if (uuid32 < 0x10000) {
2767 uuid16 = (UINT16) uuid32;
2771 /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2772 is_base_uuid = TRUE;
2773 for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
2774 if (p_uuid[xx] != base_uuid[xx]) {
2775 is_base_uuid = FALSE;
2780 if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0)) {
2781 p_uuid += (LEN_UUID_128 - 4);
2782 STREAM_TO_UINT16(uuid16, p_uuid);
2787 BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size\n");
2794 /*******************************************************************************
2796 ** Function btm_set_eir_uuid
2798 ** Description This function is called to store received UUID into inquiry result.
2800 ** Parameters p_eir - pointer of EIR significant part
2801 ** p_results - pointer of inquiry result
2805 *******************************************************************************/
2806 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2812 UINT8 type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2814 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2816 if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
2817 p_results->eir_complete_list = TRUE;
2819 p_results->eir_complete_list = FALSE;
2822 BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X\n", p_results->eir_complete_list);
2824 if ( p_uuid_data ) {
2825 for ( yy = 0; yy < num_uuid; yy++ ) {
2826 STREAM_TO_UINT16(uuid16, p_uuid_data);
2827 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2831 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2832 if ( p_uuid_data ) {
2833 for ( yy = 0; yy < num_uuid; yy++ ) {
2834 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2835 p_uuid_data += LEN_UUID_32;
2837 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2842 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2843 if ( p_uuid_data ) {
2844 for ( yy = 0; yy < num_uuid; yy++ ) {
2845 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2846 p_uuid_data += LEN_UUID_128;
2848 BTM_AddEirService( p_results->eir_uuid, uuid16 );