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 ******************************************************************************/
34 #include "controller.h"
40 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
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));
1362 btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1365 /*********************************************************************************
1367 ** Function btm_inq_stop_on_ssp
1369 ** Description This function is called on incoming SSP
1373 *******************************************************************************/
1374 void btm_inq_stop_on_ssp(void)
1376 UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1378 #if (BTM_INQ_DEBUG == TRUE)
1379 BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d\n",
1380 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);
1382 if (btm_cb.btm_inq_vars.no_inc_ssp) {
1383 if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1384 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1385 BTM_CancelPeriodicInquiry();
1386 } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1387 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1388 btsnd_hcic_inq_cancel();
1391 /* do not allow inquiry to start */
1392 btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1396 /*********************************************************************************
1398 ** Function btm_inq_clear_ssp
1400 ** Description This function is called when pairing_state becomes idle
1404 *******************************************************************************/
1405 void btm_inq_clear_ssp(void)
1407 btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1410 /*********************************************************************************
1412 ** Function btm_clr_inq_db
1414 ** Description This function is called to clear out a device or all devices
1415 ** from the inquiry database.
1417 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1418 ** (NULL clears all entries)
1422 *******************************************************************************/
1423 void btm_clr_inq_db (BD_ADDR p_bda)
1425 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1426 tINQ_DB_ENT *p_ent = p_inq->inq_db;
1429 #if (BTM_INQ_DEBUG == TRUE)
1430 BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d\n",
1431 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1433 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1434 if (p_ent->in_use) {
1435 /* If this is the specified BD_ADDR or clearing all devices */
1436 if (p_bda == NULL ||
1437 (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1438 p_ent->in_use = FALSE;
1442 #if (BTM_INQ_DEBUG == TRUE)
1443 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d\n",
1444 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1449 /*******************************************************************************
1451 ** Function btm_clr_inq_result_flt
1453 ** Description This function looks through the bdaddr database for a match
1454 ** based on Bluetooth Device Address
1456 ** Returns TRUE if found, else FALSE (new entry)
1458 *******************************************************************************/
1459 static void btm_clr_inq_result_flt (void)
1461 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1463 if (p_inq->p_bd_db) {
1464 osi_free(p_inq->p_bd_db);
1465 p_inq->p_bd_db = NULL;
1467 p_inq->num_bd_entries = 0;
1468 p_inq->max_bd_entries = 0;
1471 /*******************************************************************************
1473 ** Function btm_inq_find_bdaddr
1475 ** Description This function looks through the bdaddr database for a match
1476 ** based on Bluetooth Device Address
1478 ** Returns TRUE if found, else FALSE (new entry)
1480 *******************************************************************************/
1481 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1483 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1484 tINQ_BDADDR *p_db = &p_inq->p_bd_db[0];
1487 /* Don't bother searching, database doesn't exist or periodic mode */
1488 if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db) {
1492 for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1493 if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1494 && p_db->inq_count == p_inq->inq_counter) {
1499 if (xx < p_inq->max_bd_entries) {
1500 p_db->inq_count = p_inq->inq_counter;
1501 memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1502 p_inq->num_bd_entries++;
1505 /* If here, New Entry */
1509 /*******************************************************************************
1511 ** Function btm_inq_db_find
1513 ** Description This function looks through the inquiry database for a match
1514 ** based on Bluetooth Device Address
1516 ** Returns pointer to entry, or NULL if not found
1518 *******************************************************************************/
1519 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1522 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1524 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1525 if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1530 /* If here, not found */
1535 /*******************************************************************************
1537 ** Function btm_inq_db_new
1539 ** Description This function looks through the inquiry database for an unused
1540 ** entry. If no entry is free, it allocates the oldest entry.
1542 ** Returns pointer to entry
1544 *******************************************************************************/
1545 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1548 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1549 tINQ_DB_ENT *p_old = btm_cb.btm_inq_vars.inq_db;
1550 UINT32 ot = 0xFFFFFFFF;
1552 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1553 if (!p_ent->in_use) {
1554 memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1555 memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1556 p_ent->in_use = TRUE;
1561 if (p_ent->time_of_resp < ot) {
1563 ot = p_ent->time_of_resp;
1567 /* If here, no free entry found. Return the oldest. */
1569 memset (p_old, 0, sizeof (tINQ_DB_ENT));
1570 memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1571 p_old->in_use = TRUE;
1577 /*******************************************************************************
1579 ** Function btm_set_inq_event_filter
1581 ** Description This function is called to set the inquiry event filter.
1582 ** It is called by either internally, or by the external API function
1583 ** (BTM_SetInqEventFilter). It is used internally as part of the
1584 ** inquiry processing.
1587 ** filter_cond_type - this is the type of inquiry filter to apply:
1588 ** BTM_FILTER_COND_DEVICE_CLASS,
1589 ** BTM_FILTER_COND_BD_ADDR, or
1590 ** BTM_CLR_INQUIRY_FILTER
1592 ** p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1593 ** filter_cond_type (See section 4.7.3 of Core Spec 1.0b).
1595 ** Returns BTM_CMD_STARTED if successfully initiated
1596 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
1597 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
1599 *******************************************************************************/
1600 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1601 tBTM_INQ_FILT_COND *p_filt_cond)
1603 UINT8 condition_length = DEV_CLASS_LEN * 2;
1604 UINT8 condition_buf[DEV_CLASS_LEN * 2];
1605 UINT8 *p_cond = condition_buf; /* points to the condition to pass to HCI */
1607 #if (BTM_INQ_DEBUG == TRUE)
1608 BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]\n",
1610 BTM_TRACE_DEBUG (" condition [%02x%02x%02x %02x%02x%02x]\n",
1611 p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1612 p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1615 /* Load the correct filter condition to pass to the lower layer */
1616 switch (filter_cond_type) {
1617 case BTM_FILTER_COND_DEVICE_CLASS:
1618 /* copy the device class and device class fields into contiguous memory to send to HCI */
1619 memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1620 memcpy (&condition_buf[DEV_CLASS_LEN],
1621 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1623 /* condition length should already be set as the default */
1626 case BTM_FILTER_COND_BD_ADDR:
1627 p_cond = p_filt_cond->bdaddr_cond;
1629 /* condition length should already be set as the default */
1632 case BTM_CLR_INQUIRY_FILTER:
1633 condition_length = 0;
1637 return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1640 btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1642 /* Filter the inquiry results for the specified condition type and value */
1643 if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1644 p_cond, condition_length))
1647 return (BTM_CMD_STARTED);
1649 return (BTM_NO_RESOURCES);
1654 /*******************************************************************************
1656 ** Function btm_event_filter_complete
1658 ** Description This function is called when a set event filter has completed.
1659 ** Note: This routine currently only handles inquiry filters.
1660 ** Connection filters are ignored for now.
1664 *******************************************************************************/
1665 void btm_event_filter_complete (UINT8 *p)
1669 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1670 tBTM_CMPL_CB *p_cb = p_inq->p_inqfilter_cmpl_cb;
1672 #if (BTM_INQ_DEBUG == TRUE)
1673 BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d\n",
1674 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1676 /* If the filter complete event is from an old or cancelled request, ignore it */
1677 if (p_inq->pending_filt_complete_event) {
1678 p_inq->pending_filt_complete_event--;
1682 /* Only process the inquiry filter; Ignore the connection filter until it
1683 is used by the upper layers */
1684 if (p_inq->inqfilt_active == TRUE ) {
1685 /* Extract the returned status from the buffer */
1686 STREAM_TO_UINT8 (hci_status, p);
1687 if (hci_status != HCI_SUCCESS) {
1688 /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1689 BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)\n", hci_status);
1690 status = BTM_ERR_PROCESSING;
1692 status = BTM_SUCCESS;
1695 /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1696 callback function to notify the initiator that it has completed */
1697 if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1698 p_inq->inqfilt_active = FALSE;
1702 } else /* An inquiry is active (the set filter command was internally generated),
1703 process the next state of the process (Set a new filter or start the inquiry). */
1705 if (status != BTM_SUCCESS) {
1706 /* Process the inquiry complete (Error Status) */
1707 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1709 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1710 p_inq->inqfilt_active = FALSE;
1711 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1712 p_inq->state = BTM_INQ_INACTIVE_STATE;
1717 /* Check to see if a new filter needs to be set up */
1718 if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1719 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED) {
1720 p_inq->state = BTM_INQ_SET_FILT_STATE;
1721 } else { /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1722 p_inq->inqfilt_active = FALSE;
1724 /* Process the inquiry complete (Error Status) */
1725 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1727 } else { /* Initiate the Inquiry or Periodic Inquiry */
1728 p_inq->state = BTM_INQ_ACTIVE_STATE;
1729 p_inq->inqfilt_active = FALSE;
1730 btm_initiate_inquiry (p_inq);
1737 /*******************************************************************************
1739 ** Function btm_initiate_inquiry
1741 ** Description This function is called to start an inquiry or periodic inquiry
1742 ** upon completion of the setting and/or clearing of the inquiry filter.
1744 ** Inputs: p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1745 ** mode - GENERAL or LIMITED inquiry
1746 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1747 ** max_resps - maximum amount of devices to search for before ending the inquiry
1748 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1749 ** BTM_FILTER_COND_BD_ADDR
1750 ** filter_cond - value for the filter (based on filter_cond_type)
1752 ** Returns If an error occurs the initiator's callback is called with the error status.
1754 *******************************************************************************/
1755 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1758 tBTM_INQ_PARMS *p_inqparms = &p_inq->inqparms;
1760 #if (BTM_INQ_DEBUG == TRUE)
1761 BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d\n",
1762 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1764 btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1766 if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1767 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1771 /* Make sure the number of responses doesn't overflow the database configuration */
1772 p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1774 lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1776 if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1777 if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1778 p_inq->per_min_delay,
1779 *lap, p_inqparms->duration,
1780 p_inqparms->max_resps)) {
1781 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1784 btm_clr_inq_result_flt();
1786 /* Allocate memory to hold bd_addrs responding */
1787 if ((p_inq->p_bd_db = (tINQ_BDADDR *)osi_calloc(BT_DEFAULT_BUFFER_SIZE)) != NULL) {
1788 p_inq->max_bd_entries = (UINT16)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1789 /* BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1790 p_inq->max_bd_entries); */
1793 if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0)) {
1794 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1799 /*******************************************************************************
1801 ** Function btm_process_inq_results
1803 ** Description This function is called when inquiry results are received from
1804 ** the device. It updates the inquiry database. If the inquiry
1805 ** database is full, the oldest entry is discarded.
1807 ** Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
1808 ** BTM_INQ_RESULT_WITH_RSSI
1809 ** BTM_INQ_RESULT_EXTENDED
1813 *******************************************************************************/
1814 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1819 tBTM_INQ_RESULTS *p_cur = NULL;
1820 BOOLEAN is_new = TRUE;
1821 BOOLEAN update = FALSE;
1823 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1824 tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1825 UINT8 page_scan_rep_mode = 0;
1826 UINT8 page_scan_per_mode = 0;
1827 UINT8 page_scan_mode = 0;
1830 UINT16 clock_offset;
1831 UINT8 *p_eir_data = NULL;
1833 #if (BTM_INQ_DEBUG == TRUE)
1834 BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d inq_res_mode=%d\n",
1835 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active, inq_res_mode);
1837 /* Only process the results if the BR inquiry is still active */
1838 if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) {
1842 STREAM_TO_UINT8 (num_resp, p);
1844 for (xx = 0; xx < num_resp; xx++) {
1846 /* Extract inquiry results */
1847 STREAM_TO_BDADDR (bda, p);
1848 STREAM_TO_UINT8 (page_scan_rep_mode, p);
1849 STREAM_TO_UINT8 (page_scan_per_mode, p);
1851 if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1852 STREAM_TO_UINT8(page_scan_mode, p);
1855 STREAM_TO_DEVCLASS (dc, p);
1856 STREAM_TO_UINT16 (clock_offset, p);
1857 if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1858 STREAM_TO_UINT8(rssi, p);
1861 p_i = btm_inq_db_find (bda);
1863 /* Only process the num_resp is smaller than max_resps.
1864 If results are queued to BTU task while canceling inquiry,
1865 or when more than one result is in this response, > max_resp
1866 responses could be processed which can confuse some apps
1868 if (p_inq->inqparms.max_resps &&
1869 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1870 #if BLE_INCLUDED == TRUE
1871 /* new device response */
1873 /* exisiting device with BR/EDR info */
1874 (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1879 BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring\n");
1883 /* Check if this address has already been processed for this inquiry */
1884 if (btm_inq_find_bdaddr(bda)) {
1885 BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]\n",
1886 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
1887 /* By default suppose no update needed */
1888 i_rssi = (INT8)rssi;
1890 /* If this new RSSI is higher than the last one */
1891 if (p_inq->inqparms.report_dup && (rssi != 0) &&
1892 p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1893 #if BLE_INCLUDED == TRUE
1894 /* BR/EDR inquiry information update */
1895 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1898 p_cur = &p_i->inq_info.results;
1899 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d\n", i_rssi, p_cur->rssi);
1900 p_cur->rssi = i_rssi;
1903 /* If we received a second Extended Inq Event for an already */
1904 /* discovered device, this is because for the first one EIR was not received */
1905 else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1906 p_cur = &p_i->inq_info.results;
1909 /* If no update needed continue with next response (if any) */
1915 /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
1917 p_i = btm_inq_db_new (bda);
1921 /* If an entry for the device already exists, overwrite it ONLY if it is from
1922 a previous inquiry. (Ignore it if it is a duplicate response from the same
1925 else if (p_i->inq_count == p_inq->inq_counter
1926 #if (BLE_INCLUDED == TRUE )
1927 && (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)
1933 /* keep updating RSSI to have latest value */
1934 if ( inq_res_mode != BTM_INQ_RESULT_STANDARD ) {
1935 p_i->inq_info.results.rssi = (INT8)rssi;
1937 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1940 if (is_new == TRUE) {
1942 p_cur = &p_i->inq_info.results;
1943 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1944 p_cur->page_scan_per_mode = page_scan_per_mode;
1945 p_cur->page_scan_mode = page_scan_mode;
1946 p_cur->dev_class[0] = dc[0];
1947 p_cur->dev_class[1] = dc[1];
1948 p_cur->dev_class[2] = dc[2];
1949 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1951 p_i->time_of_resp = osi_time_get_os_boottime_ms();
1953 if (p_i->inq_count != p_inq->inq_counter) {
1954 p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
1957 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
1958 p_cur->inq_result_type = BTM_INQ_RESULT_BR;
1959 if (p_i->inq_count != p_inq->inq_counter) {
1960 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
1961 p_i->scan_rsp = FALSE;
1963 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
1966 p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
1968 /* If the number of responses found and not unlimited, issue a cancel inquiry */
1969 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1970 p_inq->inqparms.max_resps &&
1971 p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
1972 #if BLE_INCLUDED == TRUE
1973 /* BLE scanning is active and received adv */
1974 && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1975 p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1976 (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
1979 /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
1980 btsnd_hcic_inq_cancel();
1982 #if BLE_INCLUDED == TRUE
1983 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) {
1984 btm_ble_stop_inquiry();
1987 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
1989 /* Initialize flag to FALSE. This flag is set/used by application */
1990 p_i->inq_info.appl_knows_rem_name = FALSE;
1993 if (is_new || update) {
1994 if ( inq_res_mode == BTM_INQ_RESULT_EXTENDED ) {
1995 memset( p_cur->eir_uuid, 0,
1996 BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
1997 /* set bit map of UUID list from received EIR */
1998 btm_set_eir_uuid( p, p_cur );
2004 /* If a callback is registered, call it with the results */
2005 if (p_inq_results_cb) {
2006 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2012 /*******************************************************************************
2014 ** Function btm_sort_inq_result
2016 ** Description This function is called when inquiry complete is received
2017 ** from the device to sort inquiry results based on rssi.
2021 *******************************************************************************/
2022 void btm_sort_inq_result(void)
2024 UINT8 xx, yy, num_resp;
2025 tINQ_DB_ENT *p_tmp = NULL;
2026 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
2027 tINQ_DB_ENT *p_next = btm_cb.btm_inq_vars.inq_db + 1;
2030 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE) ?
2031 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp : BTM_INQ_DB_SIZE;
2033 if ((p_tmp = (tINQ_DB_ENT *)osi_malloc(sizeof(tINQ_DB_ENT))) != NULL) {
2034 size = sizeof(tINQ_DB_ENT);
2035 for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
2036 for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
2037 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
2038 memcpy (p_tmp, p_next, size);
2039 memcpy (p_next, p_ent, size);
2040 memcpy (p_ent, p_tmp, size);
2049 /*******************************************************************************
2051 ** Function btm_process_inq_complete
2053 ** Description This function is called when inquiry complete is received
2054 ** from the device. Call the callback if not in periodic inquiry
2055 ** mode AND it is not NULL (The caller wants the event).
2057 ** The callback pass back the status and the number of responses
2061 *******************************************************************************/
2062 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2064 tBTM_CMPL_CB *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2065 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2067 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2068 /* inquiry inactive case happens when inquiry is cancelled.
2069 Make mode 0 for no further inquiries from the current inquiry process
2071 if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH || !p_inq->inq_active) {
2072 /* re-initialize for next inquiry request */
2073 p_inq->next_state = BTM_BR_ONE;
2074 /* make the mode 0 here */
2075 p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2080 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2081 p_inq->inqparms.mode &= ~(mode);
2084 if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
2085 /*end of LE observe*/
2086 p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2087 p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2088 p_inq->scan_type = INQ_NONE;
2092 #if (BTM_INQ_DEBUG == TRUE)
2093 BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d\n",
2094 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2096 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2097 /* Ignore any stray or late complete messages if the inquiry is not active */
2098 if (p_inq->inq_active) {
2099 p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2101 /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2102 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0) {
2103 #if BLE_INCLUDED == TRUE
2104 btm_clear_all_pending_le_entry();
2106 p_inq->state = BTM_INQ_INACTIVE_STATE;
2108 /* Increment so the start of a next inquiry has a new count */
2109 p_inq->inq_counter++;
2111 btm_clr_inq_result_flt();
2113 if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2114 controller_get_interface()->supports_rssi_with_inquiry_results()) {
2115 btm_sort_inq_result();
2118 /* Clear the results callback if set */
2119 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2120 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2121 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2123 /* If we have a callback registered for inquiry complete, call it */
2124 BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d\n",
2125 p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2128 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2131 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2132 if (p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
2133 /* make inquiry inactive for next iteration */
2134 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2135 /* call the inquiry again */
2136 BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb, p_inq->p_inq_cmpl_cb);
2140 if (p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL) { //this inquiry is complete
2141 p_inq->scan_type = INQ_NONE;
2142 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2143 /* check if the LE observe is pending */
2144 if (p_inq->p_inq_ble_results_cb != NULL) {
2145 BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2146 BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2150 #if (BTM_INQ_DEBUG == TRUE)
2151 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d\n",
2152 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2156 /*******************************************************************************
2158 ** Function btm_process_cancel_complete
2160 ** Description This function is called when inquiry cancel complete is received
2161 ** from the device.This function will also call the btm_process_inq_complete
2162 ** This function is needed to differentiate a cancel_cmpl_evt from the
2167 *******************************************************************************/
2168 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2170 btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2171 btm_process_inq_complete(status, mode);
2173 /*******************************************************************************
2175 ** Function btm_initiate_rem_name
2177 ** Description This function looks initiates a remote name request. It is called
2178 ** either by GAP or by the API call BTM_ReadRemoteDeviceName.
2180 ** Input Params: p_cur - pointer to an inquiry result structure (NULL if nonexistent)
2181 ** p_cb - callback function called when BTM_CMD_STARTED
2183 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2187 ** BTM_CMD_STARTED is returned if the request was sent to HCI.
2188 ** BTM_BUSY if already in progress
2189 ** BTM_NO_RESOURCES if could not allocate resources to start the command
2190 ** BTM_WRONG_MODE if the device is not up.
2192 *******************************************************************************/
2193 tBTM_STATUS btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2194 UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2196 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2200 /*** Make sure the device is ready ***/
2201 if (!BTM_IsDeviceUp()) {
2202 return (BTM_WRONG_MODE);
2206 if (origin == BTM_RMT_NAME_SEC) {
2207 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2208 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2210 return BTM_CMD_STARTED;
2212 return BTM_NO_RESOURCES;
2215 /* Make sure there are no two remote name requests from external API in progress */
2216 else if (origin == BTM_RMT_NAME_EXT) {
2217 if (p_inq->remname_active) {
2220 /* If there is no remote name request running,call the callback function and start timer */
2221 p_inq->p_remname_cmpl_cb = p_cb;
2222 memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2223 btu_start_timer (&p_inq->rmt_name_timer_ent,
2224 BTU_TTYPE_BTM_RMT_NAME,
2227 /* If the database entry exists for the device, use its clock offset */
2229 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2230 p_cur->results.page_scan_rep_mode,
2231 p_cur->results.page_scan_mode,
2232 (UINT16)(p_cur->results.clock_offset |
2233 BTM_CLOCK_OFFSET_VALID));
2234 } else { /* Otherwise use defaults and mark the clock offset as invalid */
2235 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2236 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2239 p_inq->remname_active = TRUE;
2240 return BTM_CMD_STARTED;
2242 return BTM_NO_RESOURCES;
2246 return BTM_ILLEGAL_VALUE;
2250 /*******************************************************************************
2252 ** Function btm_process_remote_name
2254 ** Description This function is called when a remote name is received from
2255 ** the device. If remote names are cached, it updates the inquiry
2260 *******************************************************************************/
2261 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2263 tBTM_REMOTE_DEV_NAME rem_name;
2264 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2265 tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
2268 UINT16 temp_evt_len;
2271 BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x\n", bda[0], bda[1],
2276 BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x\n", p_inq->remname_bda[0], p_inq->remname_bda[1],
2277 p_inq->remname_bda[2], p_inq->remname_bda[3],
2278 p_inq->remname_bda[4], p_inq->remname_bda[5]);
2282 /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2283 if ((p_inq->remname_active == TRUE) &&
2285 (memcmp(bda, p_inq->remname_bda, BD_ADDR_LEN) == 0)) || bda == NULL))
2288 #if BLE_INCLUDED == TRUE
2289 if (BTM_UseLeLink(p_inq->remname_bda)) {
2290 if (hci_status == HCI_ERR_UNSPECIFIED) {
2291 btm_ble_cancel_remote_name(p_inq->remname_bda);
2295 btu_stop_timer (&p_inq->rmt_name_timer_ent);
2296 p_inq->remname_active = FALSE;
2297 /* Clean up and return the status if the command was not successful */
2298 /* Note: If part of the inquiry, the name is not stored, and the */
2299 /* inquiry complete callback is called. */
2301 if (hci_status == HCI_SUCCESS) {
2302 /* Copy the name from the data stream into the return structure */
2303 /* Note that even if it is not being returned, it is used as a */
2304 /* temporary buffer. */
2305 p_n1 = (UINT8 *)rem_name.remote_bd_name;
2306 rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2307 rem_name.remote_bd_name[rem_name.length] = 0;
2308 rem_name.status = BTM_SUCCESS;
2309 temp_evt_len = rem_name.length;
2311 while (temp_evt_len > 0) {
2315 rem_name.remote_bd_name[rem_name.length] = 0;
2319 /* If processing a stand alone remote name then report the error in the callback */
2321 rem_name.status = BTM_BAD_VALUE_RET;
2322 rem_name.length = 0;
2323 rem_name.remote_bd_name[0] = 0;
2325 /* Reset the remote BAD to zero and call callback if possible */
2326 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2328 p_inq->p_remname_cmpl_cb = NULL;
2330 (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2335 /*******************************************************************************
2337 ** Function btm_inq_rmt_name_failed
2339 ** Description This function is if timeout expires while getting remote
2340 ** name. This is done for devices that incorrectly do not
2341 ** report operation failure
2345 *******************************************************************************/
2346 void btm_inq_rmt_name_failed (void)
2348 BTM_TRACE_ERROR ("btm_inq_rmt_name_failed() remname_active=%d\n", btm_cb.btm_inq_vars.remname_active);
2350 if (btm_cb.btm_inq_vars.remname_active) {
2351 btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2353 btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2355 #if (SMP_INCLUDED == TRUE)
2356 btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2357 #endif ///SMP_INCLUDED == TRUE
2359 /*******************************************************************************
2361 ** Function btm_read_linq_tx_power_complete
2363 ** Description read inquiry tx power level complete callback function.
2367 *******************************************************************************/
2368 void btm_read_linq_tx_power_complete(UINT8 *p)
2370 tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2371 tBTM_INQ_TXPWR_RESULTS results;
2373 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2374 /* If there was a callback registered for read inq tx power, call it */
2375 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2378 STREAM_TO_UINT8 (results.hci_status, p);
2380 if (results.hci_status == HCI_SUCCESS) {
2381 results.status = BTM_SUCCESS;
2383 STREAM_TO_UINT8 (results.tx_power, p);
2384 BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n",
2385 results.tx_power, results.hci_status);
2387 results.status = BTM_ERR_PROCESSING;
2394 /*******************************************************************************
2396 ** Function BTM_WriteEIR
2398 ** Description This function is called to write EIR data to controller.
2400 ** Parameters p_buff - allocated HCI command buffer including extended
2401 ** inquriry response
2403 ** Returns BTM_SUCCESS - if successful
2404 ** BTM_MODE_UNSUPPORTED - if local device cannot support it
2406 *******************************************************************************/
2407 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2409 if (controller_get_interface()->supports_extended_inquiry_response()) {
2410 BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
2411 btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2415 return BTM_MODE_UNSUPPORTED;
2419 /*******************************************************************************
2421 ** Function BTM_CheckEirData
2423 ** Description This function is called to get EIR data from significant part.
2425 ** Parameters p_eir - pointer of EIR significant part
2426 ** type - finding EIR data type
2427 ** p_length - return the length of EIR data not including type
2429 ** Returns pointer of EIR data
2431 *******************************************************************************/
2432 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2437 BTM_TRACE_API("BTM_CheckEirData type=0x%02X\n", type);
2439 STREAM_TO_UINT8(length, p);
2440 while ( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN)) {
2441 STREAM_TO_UINT8(eir_type, p);
2442 if ( eir_type == type ) {
2443 /* length doesn't include itself */
2444 *p_length = length - 1; /* minus the length of type */
2447 p += length - 1; /* skip the length of data */
2448 STREAM_TO_UINT8(length, p);
2455 /*******************************************************************************
2457 ** Function btm_convert_uuid_to_eir_service
2459 ** Description This function is called to get the bit position of UUID.
2461 ** Parameters uuid16 - UUID 16-bit
2463 ** Returns BTM EIR service ID if found
2464 ** BTM_EIR_MAX_SERVICES - if not found
2466 *******************************************************************************/
2467 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2471 for ( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ ) {
2472 if ( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
2476 return BTM_EIR_MAX_SERVICES;
2479 /*******************************************************************************
2481 ** Function BTM_HasEirService
2483 ** Description This function is called to know if UUID in bit map of UUID.
2485 ** Parameters p_eir_uuid - bit map of UUID list
2486 ** uuid16 - UUID 16-bit
2488 ** Returns TRUE - if found
2489 ** FALSE - if not found
2491 *******************************************************************************/
2492 BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2496 service_id = btm_convert_uuid_to_eir_service(uuid16);
2497 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2498 return ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2504 /*******************************************************************************
2506 ** Function BTM_HasInquiryEirService
2508 ** Description This function is called to know if UUID in bit map of UUID list.
2510 ** Parameters p_results - inquiry results
2511 ** uuid16 - UUID 16-bit
2513 ** Returns BTM_EIR_FOUND - if found
2514 ** BTM_EIR_NOT_FOUND - if not found and it is complete list
2515 ** BTM_EIR_UNKNOWN - if not found and it is not complete list
2517 *******************************************************************************/
2518 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2520 if ( BTM_HasEirService( p_results->eir_uuid, uuid16 )) {
2521 return BTM_EIR_FOUND;
2522 } else if ( p_results->eir_complete_list ) {
2523 return BTM_EIR_NOT_FOUND;
2525 return BTM_EIR_UNKNOWN;
2529 /*******************************************************************************
2531 ** Function BTM_AddEirService
2533 ** Description This function is called to add a service in bit map of UUID list.
2535 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2536 ** uuid16 - UUID 16-bit
2540 *******************************************************************************/
2541 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2545 service_id = btm_convert_uuid_to_eir_service(uuid16);
2546 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2547 BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2551 /*******************************************************************************
2553 ** Function BTM_RemoveEirService
2555 ** Description This function is called to remove a service in bit map of UUID list.
2557 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2558 ** uuid16 - UUID 16-bit
2562 *******************************************************************************/
2563 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2567 service_id = btm_convert_uuid_to_eir_service(uuid16);
2568 if ( service_id < BTM_EIR_MAX_SERVICES ) {
2569 BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2573 /*******************************************************************************
2575 ** Function BTM_GetEirSupportedServices
2577 ** Description This function is called to get UUID list from bit map of UUID list.
2579 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2580 ** p - reference of current pointer of EIR
2581 ** max_num_uuid16 - max number of UUID can be written in EIR
2582 ** num_uuid16 - number of UUID have been written in EIR
2584 ** Returns BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2585 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2587 *******************************************************************************/
2588 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid, UINT8 **p,
2589 UINT8 max_num_uuid16, UINT8 *p_num_uuid16)
2591 UINT8 service_index;
2595 for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++) {
2596 if ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index )) {
2597 if ( *p_num_uuid16 < max_num_uuid16 ) {
2598 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2601 /* if max number of UUIDs are stored and found one more */
2603 return BTM_EIR_MORE_16BITS_UUID_TYPE;
2607 return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2610 /*******************************************************************************
2612 ** Function BTM_GetEirUuidList
2614 ** Description This function parses EIR and returns UUID list.
2616 ** Parameters p_eir - EIR
2617 ** uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2618 ** p_num_uuid - return number of UUID in found list
2619 ** p_uuid_list - return UUID list
2620 ** max_num_uuid - maximum number of UUID to be returned
2622 ** Returns 0 - if not found
2623 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2624 ** BTM_EIR_MORE_16BITS_UUID_TYPE
2625 ** BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2626 ** BTM_EIR_MORE_32BITS_UUID_TYPE
2627 ** BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2628 ** BTM_EIR_MORE_128BITS_UUID_TYPE
2630 *******************************************************************************/
2631 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2632 UINT8 *p_uuid_list, UINT8 max_num_uuid)
2637 UINT16 *p_uuid16 = (UINT16 *)p_uuid_list;
2638 UINT32 *p_uuid32 = (UINT32 *)p_uuid_list;
2639 char buff[LEN_UUID_128 * 2 + 1];
2641 p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2642 if ( p_uuid_data == NULL ) {
2646 if ( *p_num_uuid > max_num_uuid ) {
2647 BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d\n",
2648 *p_num_uuid, max_num_uuid );
2649 *p_num_uuid = max_num_uuid;
2652 BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d\n", type, *p_num_uuid );
2654 if ( uuid_size == LEN_UUID_16 ) {
2655 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2656 STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2657 BTM_TRACE_DEBUG(" 0x%04X\n", *(p_uuid16 + yy));
2659 } else if ( uuid_size == LEN_UUID_32 ) {
2660 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2661 STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2662 BTM_TRACE_DEBUG(" 0x%08X\n", *(p_uuid32 + yy));
2664 } else if ( uuid_size == LEN_UUID_128 ) {
2665 for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2666 STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2667 for ( xx = 0; xx < LEN_UUID_128; xx++ ) {
2668 sprintf(buff + xx * 2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2670 BTM_TRACE_DEBUG(" 0x%s\n", buff);
2678 /*******************************************************************************
2680 ** Function btm_eir_get_uuid_list
2682 ** Description This function searches UUID list in EIR.
2684 ** Parameters p_eir - address of EIR
2685 ** uuid_size - size of UUID to find
2686 ** p_num_uuid - number of UUIDs found
2687 ** p_uuid_list_type - EIR data type
2689 ** Returns NULL - if UUID list with uuid_size is not found
2690 ** beginning of UUID list in EIR - otherwise
2692 *******************************************************************************/
2693 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2694 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2697 UINT8 complete_type, more_type;
2700 switch ( uuid_size ) {
2702 complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2703 more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2706 complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2707 more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
2710 complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2711 more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
2719 p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2720 if (p_uuid_data == NULL) {
2721 p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2722 *p_uuid_list_type = more_type;
2724 *p_uuid_list_type = complete_type;
2727 *p_num_uuid = uuid_len / uuid_size;
2731 /*******************************************************************************
2733 ** Function btm_convert_uuid_to_uuid16
2735 ** Description This function converts UUID to UUID 16-bit.
2737 ** Parameters p_uuid - address of UUID
2738 ** uuid_size - size of UUID
2740 ** Returns 0 - if UUID cannot be converted to UUID 16-bit
2741 ** UUID 16-bit - otherwise
2743 *******************************************************************************/
2744 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2746 static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2747 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2751 BOOLEAN is_base_uuid;
2754 switch (uuid_size) {
2756 STREAM_TO_UINT16 (uuid16, p_uuid);
2759 STREAM_TO_UINT32 (uuid32, p_uuid);
2760 if (uuid32 < 0x10000) {
2761 uuid16 = (UINT16) uuid32;
2765 /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2766 is_base_uuid = TRUE;
2767 for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
2768 if (p_uuid[xx] != base_uuid[xx]) {
2769 is_base_uuid = FALSE;
2774 if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0)) {
2775 p_uuid += (LEN_UUID_128 - 4);
2776 STREAM_TO_UINT16(uuid16, p_uuid);
2781 BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size\n");
2788 /*******************************************************************************
2790 ** Function btm_set_eir_uuid
2792 ** Description This function is called to store received UUID into inquiry result.
2794 ** Parameters p_eir - pointer of EIR significant part
2795 ** p_results - pointer of inquiry result
2799 *******************************************************************************/
2800 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2806 UINT8 type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2808 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2810 if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
2811 p_results->eir_complete_list = TRUE;
2813 p_results->eir_complete_list = FALSE;
2816 BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X\n", p_results->eir_complete_list);
2818 if ( p_uuid_data ) {
2819 for ( yy = 0; yy < num_uuid; yy++ ) {
2820 STREAM_TO_UINT16(uuid16, p_uuid_data);
2821 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2825 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2826 if ( p_uuid_data ) {
2827 for ( yy = 0; yy < num_uuid; yy++ ) {
2828 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2829 p_uuid_data += LEN_UUID_32;
2831 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2836 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2837 if ( p_uuid_data ) {
2838 for ( yy = 0; yy < num_uuid; yy++ ) {
2839 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2840 p_uuid_data += LEN_UUID_128;
2842 BTM_AddEirService( p_results->eir_uuid, uuid16 );