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 "device/include/controller.h"
42 #define BTM_INQ_REPLY_TIMEOUT 3 /* 3 second timeout waiting for responses */
44 /* TRUE to enable DEBUG traces for btm_inq */
46 #define BTM_INQ_DEBUG FALSE
48 /********************************************************************************/
49 /* L O C A L D A T A D E F I N I T I O N S */
50 /********************************************************************************/
51 static const LAP general_inq_lap = {0x9e,0x8b,0x33};
52 static const LAP limited_inq_lap = {0x9e,0x8b,0x00};
54 const UINT16 BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES] =
56 UUID_SERVCLASS_SERVICE_DISCOVERY_SERVER,
57 /* UUID_SERVCLASS_BROWSE_GROUP_DESCRIPTOR, */
58 /* UUID_SERVCLASS_PUBLIC_BROWSE_GROUP, */
59 UUID_SERVCLASS_SERIAL_PORT,
60 UUID_SERVCLASS_LAN_ACCESS_USING_PPP,
61 UUID_SERVCLASS_DIALUP_NETWORKING,
62 UUID_SERVCLASS_IRMC_SYNC,
63 UUID_SERVCLASS_OBEX_OBJECT_PUSH,
64 UUID_SERVCLASS_OBEX_FILE_TRANSFER,
65 UUID_SERVCLASS_IRMC_SYNC_COMMAND,
66 UUID_SERVCLASS_HEADSET,
67 UUID_SERVCLASS_CORDLESS_TELEPHONY,
68 UUID_SERVCLASS_AUDIO_SOURCE,
69 UUID_SERVCLASS_AUDIO_SINK,
70 UUID_SERVCLASS_AV_REM_CTRL_TARGET,
71 /* UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, */
72 UUID_SERVCLASS_AV_REMOTE_CONTROL,
73 /* UUID_SERVCLASS_VIDEO_CONFERENCING, */
74 UUID_SERVCLASS_INTERCOM,
76 UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
77 /* UUID_SERVCLASS_WAP, */
78 /* UUID_SERVCLASS_WAP_CLIENT, */
82 UUID_SERVCLASS_DIRECT_PRINTING,
83 /* UUID_SERVCLASS_REFERENCE_PRINTING, */
84 UUID_SERVCLASS_IMAGING,
85 UUID_SERVCLASS_IMAGING_RESPONDER,
86 UUID_SERVCLASS_IMAGING_AUTO_ARCHIVE,
87 UUID_SERVCLASS_IMAGING_REF_OBJECTS,
88 UUID_SERVCLASS_HF_HANDSFREE,
89 UUID_SERVCLASS_AG_HANDSFREE,
90 UUID_SERVCLASS_DIR_PRT_REF_OBJ_SERVICE,
91 /* UUID_SERVCLASS_REFLECTED_UI, */
92 UUID_SERVCLASS_BASIC_PRINTING,
93 UUID_SERVCLASS_PRINTING_STATUS,
94 UUID_SERVCLASS_HUMAN_INTERFACE,
95 UUID_SERVCLASS_CABLE_REPLACEMENT,
96 UUID_SERVCLASS_HCRP_PRINT,
97 UUID_SERVCLASS_HCRP_SCAN,
98 /* UUID_SERVCLASS_COMMON_ISDN_ACCESS, */
99 /* UUID_SERVCLASS_VIDEO_CONFERENCING_GW, */
100 /* UUID_SERVCLASS_UDI_MT, */
101 /* UUID_SERVCLASS_UDI_TA, */
102 /* UUID_SERVCLASS_VCP, */
104 UUID_SERVCLASS_PBAP_PCE,
105 UUID_SERVCLASS_PBAP_PSE,
106 UUID_SERVCLASS_PHONE_ACCESS,
107 UUID_SERVCLASS_HEADSET_HS,
108 UUID_SERVCLASS_PNP_INFORMATION,
109 /* UUID_SERVCLASS_GENERIC_NETWORKING, */
110 /* UUID_SERVCLASS_GENERIC_FILETRANSFER, */
111 /* UUID_SERVCLASS_GENERIC_AUDIO, */
112 /* UUID_SERVCLASS_GENERIC_TELEPHONY, */
113 /* UUID_SERVCLASS_UPNP_SERVICE, */
114 /* UUID_SERVCLASS_UPNP_IP_SERVICE, */
115 /* UUID_SERVCLASS_ESDP_UPNP_IP_PAN, */
116 /* UUID_SERVCLASS_ESDP_UPNP_IP_LAP, */
117 /* UUID_SERVCLASS_ESDP_UPNP_IP_L2CAP, */
118 UUID_SERVCLASS_VIDEO_SOURCE,
119 UUID_SERVCLASS_VIDEO_SINK,
120 /* UUID_SERVCLASS_VIDEO_DISTRIBUTION */
121 UUID_SERVCLASS_MESSAGE_ACCESS,
122 UUID_SERVCLASS_MESSAGE_NOTIFICATION,
123 UUID_SERVCLASS_HDP_SOURCE,
124 UUID_SERVCLASS_HDP_SINK
127 /********************************************************************************/
128 /* L O C A L F U N C T I O N P R O T O T Y P E S */
129 /********************************************************************************/
130 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq);
131 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type, tBTM_INQ_FILT_COND *p_filt_cond);
132 static void btm_clr_inq_result_flt (void);
134 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 );
135 static void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results );
136 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
137 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type );
138 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size );
140 /*******************************************************************************
142 ** Function BTM_SetDiscoverability
144 ** Description This function is called to set the device into or out of
145 ** discoverable mode. Discoverable mode means inquiry
146 ** scans are enabled. If a value of '0' is entered for window or
147 ** interval, the default values are used.
149 ** Returns BTM_SUCCESS if successful
150 ** BTM_BUSY if a setting of the filter is already in progress
151 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
152 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
153 ** BTM_WRONG_MODE if the device is not up.
155 *******************************************************************************/
156 tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 interval)
159 UINT16 service_class;
167 BTM_TRACE_API ("BTM_SetDiscoverability");
168 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
169 if (controller_get_interface()->supports_ble())
171 if (btm_ble_set_discoverability((UINT16)(inq_mode))
174 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
175 btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
178 inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
181 /*** Check mode parameter ***/
182 if (inq_mode > BTM_MAX_DISCOVERABLE)
183 return (BTM_ILLEGAL_VALUE);
185 /* Make sure the controller is active */
186 if (!controller_get_interface()->get_is_ready())
187 return (BTM_DEV_RESET);
189 /* If the window and/or interval is '0', set to default values */
191 window = BTM_DEFAULT_DISC_WINDOW;
194 interval = BTM_DEFAULT_DISC_INTERVAL;
196 BTM_TRACE_API ("BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window 0x%04x, interval 0x%04x",
197 inq_mode, window, interval);
199 /*** Check for valid window and interval parameters ***/
200 /*** Only check window and duration if mode is connectable ***/
201 if (inq_mode != BTM_NON_DISCOVERABLE)
203 /* window must be less than or equal to interval */
204 if (window < HCI_MIN_INQUIRYSCAN_WINDOW ||
205 window > HCI_MAX_INQUIRYSCAN_WINDOW ||
206 interval < HCI_MIN_INQUIRYSCAN_INTERVAL ||
207 interval > HCI_MAX_INQUIRYSCAN_INTERVAL ||
210 return (BTM_ILLEGAL_VALUE);
214 /* Set the IAC if needed */
215 if (inq_mode != BTM_NON_DISCOVERABLE)
217 if (inq_mode & BTM_LIMITED_DISCOVERABLE)
219 /* Use the GIAC and LIAC codes for limited discoverable mode */
220 memcpy (temp_lap[0], limited_inq_lap, LAP_LEN);
221 memcpy (temp_lap[1], general_inq_lap, LAP_LEN);
223 if (!btsnd_hcic_write_cur_iac_lap (2, (LAP * const) temp_lap))
224 return (BTM_NO_RESOURCES); /* Cannot continue */
228 if (!btsnd_hcic_write_cur_iac_lap (1, (LAP * const) &general_inq_lap))
229 return (BTM_NO_RESOURCES); /* Cannot continue */
232 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
235 /* Send down the inquiry scan window and period if changed */
236 if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
237 (interval != btm_cb.btm_inq_vars.inq_scan_period))
239 if (btsnd_hcic_write_inqscan_cfg (interval, window))
241 btm_cb.btm_inq_vars.inq_scan_window = window;
242 btm_cb.btm_inq_vars.inq_scan_period = interval;
245 return (BTM_NO_RESOURCES);
248 if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK)
249 scan_mode |= HCI_PAGE_SCAN_ENABLED;
251 if (btsnd_hcic_write_scan_enable (scan_mode))
253 btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
254 btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
257 return (BTM_NO_RESOURCES);
259 /* Change the service class bit if mode has changed */
260 p_cod = BTM_ReadDeviceClass();
261 BTM_COD_SERVICE_CLASS(service_class, p_cod);
262 is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? TRUE : FALSE;
263 cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? TRUE : FALSE;
264 if (is_limited ^ cod_limited)
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;
273 FIELDS_TO_COD(cod, minor, major, service_class);
274 (void) BTM_SetDeviceClass (cod);
277 return (BTM_SUCCESS);
280 /*******************************************************************************
282 ** Function BTM_SetInquiryScanType
284 ** Description This function is called to set the iquiry scan-type to
285 ** standard or interlaced.
287 ** Returns BTM_SUCCESS if successful
288 ** BTM_MODE_UNSUPPORTED if not a 1.2 device
289 ** BTM_WRONG_MODE if the device is not up.
291 *******************************************************************************/
292 tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type)
295 BTM_TRACE_API ("BTM_SetInquiryScanType");
296 if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED)
297 return (BTM_ILLEGAL_VALUE);
299 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
300 if (!controller_get_interface()->supports_interlaced_inquiry_scan())
301 return (BTM_MODE_UNSUPPORTED);
303 /* Check for scan type if configuration has been changed */
304 if (scan_type != btm_cb.btm_inq_vars.inq_scan_type)
306 if (BTM_IsDeviceUp())
308 if (btsnd_hcic_write_inqscan_type ((UINT8)scan_type))
309 btm_cb.btm_inq_vars.inq_scan_type = scan_type;
311 return (BTM_NO_RESOURCES);
313 else return (BTM_WRONG_MODE);
315 return (BTM_SUCCESS);
318 /*******************************************************************************
320 ** Function BTM_SetPageScanType
322 ** Description This function is called to set the page scan-type to
323 ** standard or interlaced.
325 ** Returns BTM_SUCCESS if successful
326 ** BTM_MODE_UNSUPPORTED if not a 1.2 device
327 ** BTM_WRONG_MODE if the device is not up.
329 *******************************************************************************/
330 tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type)
332 BTM_TRACE_API ("BTM_SetPageScanType");
333 if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED)
334 return (BTM_ILLEGAL_VALUE);
336 /* whatever app wants if device is not 1.2 scan type should be STANDARD */
337 if (!controller_get_interface()->supports_interlaced_inquiry_scan())
338 return (BTM_MODE_UNSUPPORTED);
340 /* Check for scan type if configuration has been changed */
341 if (scan_type != btm_cb.btm_inq_vars.page_scan_type)
343 if (BTM_IsDeviceUp())
345 if (btsnd_hcic_write_pagescan_type ((UINT8)scan_type))
346 btm_cb.btm_inq_vars.page_scan_type = scan_type;
348 return (BTM_NO_RESOURCES);
350 else return (BTM_WRONG_MODE);
352 return (BTM_SUCCESS);
356 /*******************************************************************************
358 ** Function BTM_SetInquiryMode
360 ** Description This function is called to set standard or with RSSI
361 ** mode of the inquiry for local device.
363 ** Output Params: mode - standard, with RSSI, extended
365 ** Returns BTM_SUCCESS if successful
366 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
367 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
368 ** BTM_WRONG_MODE if the device is not up.
370 *******************************************************************************/
371 tBTM_STATUS BTM_SetInquiryMode (UINT8 mode)
373 const controller_t *controller = controller_get_interface();
374 BTM_TRACE_API ("BTM_SetInquiryMode");
375 if (mode == BTM_INQ_RESULT_STANDARD)
379 else if (mode == BTM_INQ_RESULT_WITH_RSSI)
381 if (!controller->supports_rssi_with_inquiry_results())
382 return (BTM_MODE_UNSUPPORTED);
384 else if (mode == BTM_INQ_RESULT_EXTENDED)
386 if (!controller->supports_extended_inquiry_response())
387 return (BTM_MODE_UNSUPPORTED);
390 return (BTM_ILLEGAL_VALUE);
392 if (!BTM_IsDeviceUp())
393 return (BTM_WRONG_MODE);
395 if (!btsnd_hcic_write_inquiry_mode (mode))
396 return (BTM_NO_RESOURCES);
398 return (BTM_SUCCESS);
401 /*******************************************************************************
403 ** Function BTM_ReadDiscoverability
405 ** Description This function is called to read the current discoverability
406 ** mode of the device.
408 ** Output Params: p_window - current inquiry scan duration
409 ** p_interval - current inquiry scan interval
411 ** Returns BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
412 ** BTM_GENERAL_DISCOVERABLE
414 *******************************************************************************/
415 UINT16 BTM_ReadDiscoverability (UINT16 *p_window, UINT16 *p_interval)
417 BTM_TRACE_API ("BTM_ReadDiscoverability");
419 *p_window = btm_cb.btm_inq_vars.inq_scan_window;
422 *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
424 return (btm_cb.btm_inq_vars.discoverable_mode);
428 /*******************************************************************************
430 ** Function BTM_SetPeriodicInquiryMode
432 ** Description This function is called to set the device periodic inquiry mode.
433 ** If the duration is zero, the periodic inquiry mode is cancelled.
435 ** Note: We currently do not allow concurrent inquiry and periodic inquiry.
437 ** Parameters: p_inqparms - pointer to the inquiry information
438 ** mode - GENERAL or LIMITED inquiry
439 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
440 ** max_resps - maximum amount of devices to search for before ending the inquiry
441 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
442 ** BTM_FILTER_COND_BD_ADDR
443 ** filter_cond - value for the filter (based on filter_cond_type)
445 ** max_delay - maximum amount of time between successive inquiries
446 ** min_delay - minimum amount of time between successive inquiries
447 ** p_results_cb - callback returning pointer to results (tBTM_INQ_RESULTS)
449 ** Returns BTM_CMD_STARTED if successfully started
450 ** BTM_ILLEGAL_VALUE if a bad parameter is detected
451 ** BTM_NO_RESOURCES if could not allocate a message buffer
452 ** BTM_SUCCESS - if cancelling the periodic inquiry
453 ** BTM_BUSY - if an inquiry is already active
454 ** BTM_WRONG_MODE if the device is not up.
456 *******************************************************************************/
457 tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_delay,
458 UINT16 min_delay, tBTM_INQ_RESULTS_CB *p_results_cb)
461 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
463 BTM_TRACE_API ("BTM_SetPeriodicInquiryMode: mode: %d, dur: %d, rsps: %d, flt: %d, min: %d, max: %d",
464 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
465 p_inqparms->filter_cond_type, min_delay, max_delay);
467 /*** Make sure the device is ready ***/
468 if (!BTM_IsDeviceUp())
469 return (BTM_WRONG_MODE);
471 /* Only one active inquiry is allowed in this implementation.
472 Also do not allow an inquiry if the inquiry filter is being updated */
473 if (p_inq->inq_active || p_inq->inqfilt_active)
476 /* If illegal parameters return FALSE */
477 if (p_inqparms->mode != BTM_GENERAL_INQUIRY &&
478 p_inqparms->mode != BTM_LIMITED_INQUIRY)
479 return (BTM_ILLEGAL_VALUE);
481 /* Verify the parameters for this command */
482 if (p_inqparms->duration < BTM_MIN_INQUIRY_LEN ||
483 p_inqparms->duration > BTM_MAX_INQUIRY_LENGTH ||
484 min_delay <= p_inqparms->duration ||
485 min_delay < BTM_PER_INQ_MIN_MIN_PERIOD ||
486 min_delay > BTM_PER_INQ_MAX_MIN_PERIOD ||
487 max_delay <= min_delay ||
488 max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
489 /* max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
490 /* BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
492 return (BTM_ILLEGAL_VALUE);
495 /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
496 p_inq->inqparms = *p_inqparms;
497 p_inq->per_min_delay = min_delay;
498 p_inq->per_max_delay = max_delay;
499 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
500 p_inq->p_inq_results_cb = p_results_cb;
502 p_inq->inq_active = (UINT8)((p_inqparms->mode == BTM_LIMITED_INQUIRY) ?
503 (BTM_LIMITED_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE) :
504 (BTM_GENERAL_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE));
506 /* If a filter is specified, then save it for later and clear the current filter.
507 The setting of the filter is done upon completion of clearing of the previous
510 if (p_inqparms->filter_cond_type != BTM_CLR_INQUIRY_FILTER)
512 p_inq->state = BTM_INQ_CLR_FILT_STATE;
513 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
515 else /* The filter is not being used so simply clear it; the inquiry can start after this operation */
516 p_inq->state = BTM_INQ_SET_FILT_STATE;
518 /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
519 if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type, &p_inqparms->filter_cond)) != BTM_CMD_STARTED)
521 /* If set filter command is not succesful reset the state */
522 p_inq->p_inq_results_cb = NULL;
523 p_inq->state = BTM_INQ_INACTIVE_STATE;
531 /*******************************************************************************
533 ** Function BTM_CancelPeriodicInquiry
535 ** Description This function cancels a periodic inquiry
538 ** BTM_NO_RESOURCES if could not allocate a message buffer
539 ** BTM_SUCCESS - if cancelling the periodic inquiry
540 ** BTM_WRONG_MODE if the device is not up.
542 *******************************************************************************/
543 tBTM_STATUS BTM_CancelPeriodicInquiry(void)
545 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
546 tBTM_STATUS status = BTM_SUCCESS;
547 BTM_TRACE_API ("BTM_CancelPeriodicInquiry called");
549 /*** Make sure the device is ready ***/
550 if (!BTM_IsDeviceUp())
551 return (BTM_WRONG_MODE);
553 /* Only cancel if one is active */
554 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
556 btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
557 btm_cb.btm_inq_vars.p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
559 if (!btsnd_hcic_exit_per_inq ())
560 status = BTM_NO_RESOURCES;
562 /* If the event filter is in progress, mark it so that the processing of the return
563 event will be ignored */
564 if(p_inq->inqfilt_active)
565 p_inq->pending_filt_complete_event++;
567 p_inq->inqfilt_active = FALSE;
568 p_inq->inq_counter++;
575 /*******************************************************************************
577 ** Function BTM_SetConnectability
579 ** Description This function is called to set the device into or out of
580 ** connectable mode. Discoverable mode means page scans enabled.
582 ** Returns BTM_SUCCESS if successful
583 ** BTM_ILLEGAL_VALUE if a bad parameter is detected
584 ** BTM_NO_RESOURCES if could not allocate a message buffer
585 ** BTM_WRONG_MODE if the device is not up.
587 *******************************************************************************/
588 tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 interval)
591 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
593 BTM_TRACE_API ("BTM_SetConnectability");
595 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
596 if (controller_get_interface()->supports_ble())
598 if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
600 return BTM_NO_RESOURCES;
602 p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
603 p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
605 page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
608 /*** Check mode parameter ***/
609 if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE)
610 return (BTM_ILLEGAL_VALUE);
612 /* Make sure the controller is active */
613 if (!controller_get_interface()->get_is_ready())
614 return (BTM_DEV_RESET);
616 /* If the window and/or interval is '0', set to default values */
618 window = BTM_DEFAULT_CONN_WINDOW;
621 interval = BTM_DEFAULT_CONN_INTERVAL;
623 BTM_TRACE_API ("BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, interval 0x%04x",
624 page_mode, window, interval);
626 /*** Check for valid window and interval parameters ***/
627 /*** Only check window and duration if mode is connectable ***/
628 if (page_mode == BTM_CONNECTABLE)
630 /* window must be less than or equal to interval */
631 if (window < HCI_MIN_PAGESCAN_WINDOW ||
632 window > HCI_MAX_PAGESCAN_WINDOW ||
633 interval < HCI_MIN_PAGESCAN_INTERVAL ||
634 interval > HCI_MAX_PAGESCAN_INTERVAL ||
637 return (BTM_ILLEGAL_VALUE);
640 scan_mode |= HCI_PAGE_SCAN_ENABLED;
643 if ((window != p_inq->page_scan_window) ||
644 (interval != p_inq->page_scan_period))
646 p_inq->page_scan_window = window;
647 p_inq->page_scan_period = interval;
648 if (!btsnd_hcic_write_pagescan_cfg (interval, window))
649 return (BTM_NO_RESOURCES);
652 /* Keep the inquiry scan as previouosly set */
653 if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK)
654 scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
656 if (btsnd_hcic_write_scan_enable (scan_mode))
658 p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
659 p_inq->connectable_mode |= page_mode;
661 return (BTM_SUCCESS);
664 return (BTM_NO_RESOURCES);
668 /*******************************************************************************
670 ** Function BTM_ReadConnectability
672 ** Description This function is called to read the current discoverability
673 ** mode of the device.
674 ** Output Params p_window - current page scan duration
675 ** p_interval - current time between page scans
677 ** Returns BTM_NON_CONNECTABLE or BTM_CONNECTABLE
679 *******************************************************************************/
680 UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval)
682 BTM_TRACE_API ("BTM_ReadConnectability");
684 *p_window = btm_cb.btm_inq_vars.page_scan_window;
687 *p_interval = btm_cb.btm_inq_vars.page_scan_period;
689 return (btm_cb.btm_inq_vars.connectable_mode);
694 /*******************************************************************************
696 ** Function BTM_IsInquiryActive
698 ** Description This function returns a bit mask of the current inquiry state
700 ** Returns BTM_INQUIRY_INACTIVE if inactive (0)
701 ** BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active
702 ** BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active
703 ** BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active
705 *******************************************************************************/
706 UINT16 BTM_IsInquiryActive (void)
708 BTM_TRACE_API ("BTM_IsInquiryActive");
710 return(btm_cb.btm_inq_vars.inq_active);
715 /*******************************************************************************
717 ** Function BTM_CancelInquiry
719 ** Description This function cancels an inquiry if active
721 ** Returns BTM_SUCCESS if successful
722 ** BTM_NO_RESOURCES if could not allocate a message buffer
723 ** BTM_WRONG_MODE if the device is not up.
725 *******************************************************************************/
726 tBTM_STATUS BTM_CancelInquiry(void)
728 tBTM_STATUS status = BTM_SUCCESS;
729 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
730 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
731 UINT8 active_mode=p_inq->inq_active;
733 BTM_TRACE_API ("BTM_CancelInquiry called");
735 /*** Make sure the device is ready ***/
736 if (!BTM_IsDeviceUp())
737 return (BTM_WRONG_MODE);
739 /* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
740 if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
741 (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
743 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
744 p_inq->state = BTM_INQ_INACTIVE_STATE;
745 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; /* Do not notify caller anymore */
746 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL; /* Do not notify caller anymore */
748 /* If the event filter is in progress, mark it so that the processing of the return
749 event will be ignored */
750 if (p_inq->inqfilt_active)
752 p_inq->inqfilt_active = FALSE;
753 p_inq->pending_filt_complete_event++;
755 /* Initiate the cancel inquiry */
758 if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
759 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
760 &&(active_mode & BTM_BR_INQUIRY_MASK)
764 if (!btsnd_hcic_inq_cancel())
765 status = BTM_NO_RESOURCES;
767 #if BLE_INCLUDED == TRUE
768 if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
769 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
770 &&(active_mode & BTM_BLE_INQ_ACTIVE_MASK)
773 btm_ble_stop_inquiry();
777 /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
778 * and then send the BUSY_LEVEL event
779 * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
782 p_inq->inq_counter++;
783 btm_clr_inq_result_flt();
790 /*******************************************************************************
792 ** Function BTM_StartInquiry
794 ** Description This function is called to start an inquiry.
796 ** Parameters: p_inqparms - pointer to the inquiry information
797 ** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
798 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
799 ** max_resps - maximum amount of devices to search for before ending the inquiry
800 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
801 ** BTM_FILTER_COND_BD_ADDR
802 ** filter_cond - value for the filter (based on filter_cond_type)
804 ** p_results_cb - Pointer to the callback routine which gets called
805 ** upon receipt of an inquiry result. If this field is
806 ** NULL, the application is not notified.
808 ** p_cmpl_cb - Pointer to the callback routine which gets called
809 ** upon completion. If this field is NULL, the
810 ** application is not notified when completed.
811 ** Returns tBTM_STATUS
812 ** BTM_CMD_STARTED if successfully initiated
813 ** BTM_BUSY if already in progress
814 ** BTM_ILLEGAL_VALUE if parameter(s) are out of range
815 ** BTM_NO_RESOURCES if could not allocate resources to start the command
816 ** BTM_WRONG_MODE if the device is not up.
818 *******************************************************************************/
819 tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
820 tBTM_CMPL_CB *p_cmpl_cb)
822 tBTM_STATUS status = BTM_CMD_STARTED;
823 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
825 BTM_TRACE_API ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
826 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
827 p_inqparms->filter_cond_type);
829 /* Only one active inquiry is allowed in this implementation.
830 Also do not allow an inquiry if the inquiry filter is being updated */
831 if (p_inq->inq_active || p_inq->inqfilt_active)
833 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
834 /*check if LE observe is already running*/
835 if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL)
837 BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
838 p_inq->scan_type = INQ_GENERAL;
839 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
840 btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
841 btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
847 BTM_TRACE_API("BTM_StartInquiry: return BUSY");
851 p_inq->scan_type = INQ_GENERAL;
853 /*** Make sure the device is ready ***/
854 if (!BTM_IsDeviceUp())
855 return (BTM_WRONG_MODE);
857 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
858 (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
859 #if (BLE_INCLUDED == TRUE)
860 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
861 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
864 return (BTM_ILLEGAL_VALUE);
866 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
867 if(p_inq->next_state==BTM_FINISH)
868 return BTM_ILLEGAL_VALUE;
872 /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
873 p_inq->inqparms = *p_inqparms;
875 /* Initialize the inquiry variables */
876 p_inq->state = BTM_INQ_ACTIVE_STATE;
877 p_inq->p_inq_cmpl_cb = p_cmpl_cb;
878 p_inq->p_inq_results_cb = p_results_cb;
879 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
880 p_inq->inq_active = p_inqparms->mode;
882 BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
884 /* interleave scan minimal conditions */
885 #if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE))
887 /* check if both modes are present */
888 if((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) && (p_inqparms->mode & BTM_BR_INQUIRY_MASK))
890 BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
891 p_inqparms->duration=p_inqparms->intl_duration[p_inq->next_state];
892 p_inq->inqparms.duration=p_inqparms->duration;
896 BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x", p_inqparms->mode);
897 p_inq->next_state=BTM_NO_INTERLEAVING;
903 /* start LE inquiry here if requested */
904 #if BLE_INCLUDED == TRUE
905 if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
906 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
907 &&(p_inq->next_state==BTM_BLE_ONE || p_inq->next_state==BTM_BLE_TWO ||
908 p_inq->next_state==BTM_NO_INTERLEAVING)
913 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
914 p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
915 BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
916 p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
918 if (!controller_get_interface()->supports_ble())
920 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
921 status = BTM_ILLEGAL_VALUE;
923 /* BLE for now does not support filter condition for inquiry */
924 else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
925 p_inqparms->duration)) != BTM_CMD_STARTED)
927 BTM_TRACE_ERROR("Err Starting LE Inquiry.");
928 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
930 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
931 p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
934 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
935 if(p_inq->next_state==BTM_NO_INTERLEAVING)
937 p_inq->next_state=BTM_FINISH;
941 BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d",
942 p_inq->next_state+1);
943 p_inq->next_state+=1;
945 /* reset next_state if status <> BTM_Started */
946 if(status!=BTM_CMD_STARTED)
947 p_inq->next_state=BTM_BR_ONE;
949 /* if interleave scan..return here */
954 BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
956 #endif /* end of BLE_INCLUDED */
958 /* we're done with this routine if BR/EDR inquiry is not desired. */
959 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
962 /* BR/EDR inquiry portion */
963 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
964 if((p_inq->next_state==BTM_BR_ONE || p_inq->next_state==BTM_BR_TWO ||
965 p_inq->next_state==BTM_NO_INTERLEAVING ))
967 p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
969 /* If a filter is specified, then save it for later and clear the current filter.
970 The setting of the filter is done upon completion of clearing of the previous
973 switch (p_inqparms->filter_cond_type)
975 case BTM_CLR_INQUIRY_FILTER:
976 p_inq->state = BTM_INQ_SET_FILT_STATE;
979 case BTM_FILTER_COND_DEVICE_CLASS:
980 case BTM_FILTER_COND_BD_ADDR:
981 /* The filter is not being used so simply clear it;
982 the inquiry can start after this operation */
983 p_inq->state = BTM_INQ_CLR_FILT_STATE;
984 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
985 /* =============>>>> adding LE filtering here ????? */
989 return (BTM_ILLEGAL_VALUE);
992 /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
993 if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
994 &p_inqparms->filter_cond)) != BTM_CMD_STARTED)
995 p_inq->state = BTM_INQ_INACTIVE_STATE;
997 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
998 if (p_inq->next_state==BTM_NO_INTERLEAVING)
999 p_inq->next_state=BTM_FINISH;
1002 BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
1003 p_inq->next_state+1);
1004 p_inq->next_state+=1;
1007 if (status!=BTM_CMD_STARTED)
1009 /* Some error beginning the scan process.
1010 Reset the next_state parameter.. Do we need to reset the inq_active also?
1012 BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x", status);
1013 p_inq->next_state=BTM_BR_ONE;
1022 /*******************************************************************************
1024 ** Function BTM_ReadRemoteDeviceName
1026 ** Description This function initiates a remote device HCI command to the
1027 ** controller and calls the callback when the process has completed.
1029 ** Input Params: remote_bda - device address of name to retrieve
1030 ** p_cb - callback function called when BTM_CMD_STARTED
1032 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
1036 ** BTM_CMD_STARTED is returned if the request was successfully sent
1038 ** BTM_BUSY if already in progress
1039 ** BTM_UNKNOWN_ADDR if device address is bad
1040 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1041 ** BTM_WRONG_MODE if the device is not up.
1043 *******************************************************************************/
1044 tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
1045 ,tBT_TRANSPORT transport)
1047 tBTM_INQ_INFO *p_cur = NULL;
1050 BTM_TRACE_API ("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]",
1051 remote_bda[0], remote_bda[1], remote_bda[2],
1052 remote_bda[3], remote_bda[4], remote_bda[5]);
1054 /* Use the remote device's clock offset if it is in the local inquiry database */
1055 if ((p_i = btm_inq_db_find (remote_bda)) != NULL)
1057 p_cur = &p_i->inq_info;
1059 BTM_TRACE_API ("no device found in inquiry db");
1061 #if (BLE_INCLUDED == TRUE)
1062 if (transport == BT_TRANSPORT_LE)
1064 return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
1069 return (btm_initiate_rem_name (remote_bda, p_cur, BTM_RMT_NAME_EXT,
1070 BTM_EXT_RMT_NAME_TIMEOUT, p_cb));
1073 /*******************************************************************************
1075 ** Function BTM_CancelRemoteDeviceName
1077 ** Description This function initiates the cancel request for the specified
1080 ** Input Params: None
1083 ** BTM_CMD_STARTED is returned if the request was successfully sent
1085 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1086 ** BTM_WRONG_MODE if there is not an active remote name request.
1088 *******************************************************************************/
1089 tBTM_STATUS BTM_CancelRemoteDeviceName (void)
1091 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1093 BTM_TRACE_API ("BTM_CancelRemoteDeviceName()");
1095 /* Make sure there is not already one in progress */
1096 if (p_inq->remname_active)
1098 #if BLE_INCLUDED == TRUE
1099 if (BTM_UseLeLink(p_inq->remname_bda))
1101 if (btm_ble_cancel_remote_name(p_inq->remname_bda))
1102 return (BTM_CMD_STARTED);
1104 return (BTM_UNKNOWN_ADDR);
1108 if (btsnd_hcic_rmt_name_req_cancel (p_inq->remname_bda))
1109 return (BTM_CMD_STARTED);
1111 return (BTM_NO_RESOURCES);
1114 return (BTM_WRONG_MODE);
1117 /*******************************************************************************
1119 ** Function BTM_InqDbRead
1121 ** Description This function looks through the inquiry database for a match
1122 ** based on Bluetooth Device Address. This is the application's
1123 ** interface to get the inquiry details of a specific BD address.
1125 ** Returns pointer to entry, or NULL if not found
1127 *******************************************************************************/
1128 tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
1130 BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]",
1131 p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
1133 tINQ_DB_ENT *p_ent = btm_inq_db_find(p_bda);
1137 return &p_ent->inq_info;
1141 /*******************************************************************************
1143 ** Function BTM_InqDbFirst
1145 ** Description This function looks through the inquiry database for the first
1146 ** used entry, and returns that. This is used in conjunction with
1147 ** BTM_InqDbNext by applications as a way to walk through the
1148 ** inquiry database.
1150 ** Returns pointer to first in-use entry, or NULL if DB is empty
1152 *******************************************************************************/
1153 tBTM_INQ_INFO *BTM_InqDbFirst (void)
1156 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1158 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1161 return (&p_ent->inq_info);
1164 /* If here, no used entry found */
1165 return ((tBTM_INQ_INFO *)NULL);
1169 /*******************************************************************************
1171 ** Function BTM_InqDbNext
1173 ** Description This function looks through the inquiry database for the next
1174 ** used entry, and returns that. If the input parameter is NULL,
1175 ** the first entry is returned.
1177 ** Returns pointer to next in-use entry, or NULL if no more found.
1179 *******************************************************************************/
1180 tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur)
1187 p_ent = (tINQ_DB_ENT *) ((UINT8 *)p_cur - offsetof (tINQ_DB_ENT, inq_info));
1188 inx = (UINT16)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1190 for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++)
1193 return (&p_ent->inq_info);
1196 /* If here, more entries found */
1197 return ((tBTM_INQ_INFO *)NULL);
1200 return (BTM_InqDbFirst());
1204 /*******************************************************************************
1206 ** Function BTM_ClearInqDb
1208 ** Description This function is called to clear out a device or all devices
1209 ** from the inquiry database.
1211 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1212 ** (NULL clears all entries)
1214 ** Returns BTM_BUSY if an inquiry, get remote name, or event filter
1215 ** is active, otherwise BTM_SUCCESS
1217 *******************************************************************************/
1218 tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda)
1220 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1222 /* If an inquiry or remote name is in progress return busy */
1223 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE ||
1224 p_inq->inqfilt_active)
1227 btm_clr_inq_db(p_bda);
1229 return (BTM_SUCCESS);
1232 /*******************************************************************************
1234 ** Function BTM_ReadInquiryRspTxPower
1236 ** Description This command will read the inquiry Transmit Power level used
1237 ** to transmit the FHS and EIR data packets.
1238 ** This can be used directly in the Tx Power Level EIR data type.
1240 ** Returns BTM_SUCCESS if successful
1242 *******************************************************************************/
1243 tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb)
1245 if (btm_cb.devcb.p_txpwer_cmpl_cb)
1248 btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT );
1251 btm_cb.devcb.p_txpwer_cmpl_cb = p_cb;
1253 if (!btsnd_hcic_read_inq_tx_power ())
1255 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
1256 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
1257 return (BTM_NO_RESOURCES);
1260 return (BTM_CMD_STARTED);
1263 /*********************************************************************************
1264 **********************************************************************************
1266 ** BTM Internal Inquiry Functions **
1268 **********************************************************************************
1269 *********************************************************************************/
1270 /*******************************************************************************
1272 ** Function btm_inq_db_reset
1274 ** Description This function is called at at reset to clear the inquiry
1275 ** database & pending callback.
1279 *******************************************************************************/
1280 void btm_inq_db_reset (void)
1282 tBTM_REMOTE_DEV_NAME rem_name;
1283 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1284 UINT8 num_responses;
1285 UINT8 temp_inq_active;
1288 btu_stop_timer (&p_inq->inq_timer_ent);
1290 /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
1291 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE)
1293 temp_inq_active = p_inq->inq_active; /* Save so state can change BEFORE
1294 callback is called */
1295 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1297 /* If not a periodic inquiry, the complete callback must be called to notify caller */
1298 if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
1299 temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE)
1301 if (p_inq->p_inq_cmpl_cb)
1304 (*p_inq->p_inq_cmpl_cb)(&num_responses);
1309 /* Cancel a remote name request if active, and notify the caller (if waiting) */
1310 if (p_inq->remname_active )
1312 btu_stop_timer (&p_inq->rmt_name_timer_ent);
1313 p_inq->remname_active = FALSE;
1314 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
1316 if (p_inq->p_remname_cmpl_cb)
1318 rem_name.status = BTM_DEV_RESET;
1320 (*p_inq->p_remname_cmpl_cb)(&rem_name);
1321 p_inq->p_remname_cmpl_cb = NULL;
1325 /* Cancel an inquiry filter request if active, and notify the caller (if waiting) */
1326 if (p_inq->inqfilt_active)
1328 p_inq->inqfilt_active = FALSE;
1330 if (p_inq->p_inqfilter_cmpl_cb)
1332 status = BTM_DEV_RESET;
1333 (*p_inq->p_inqfilter_cmpl_cb)(&status);
1337 p_inq->state = BTM_INQ_INACTIVE_STATE;
1338 p_inq->pending_filt_complete_event = 0;
1339 p_inq->p_inq_results_cb = NULL;
1340 btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
1341 btm_clr_inq_result_flt();
1343 p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1344 p_inq->connectable_mode = BTM_NON_CONNECTABLE;
1345 p_inq->page_scan_type = BTM_SCAN_TYPE_STANDARD;
1346 p_inq->inq_scan_type = BTM_SCAN_TYPE_STANDARD;
1348 #if BLE_INCLUDED == TRUE
1349 p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1350 p_inq->connectable_mode |= BTM_BLE_NON_CONNECTABLE;
1356 /*********************************************************************************
1358 ** Function btm_inq_db_init
1360 ** Description This function is called at startup to initialize the inquiry
1365 *******************************************************************************/
1366 void btm_inq_db_init (void)
1368 #if 0 /* cleared in btm_init; put back in if called from anywhere else! */
1369 memset (&btm_cb.btm_inq_vars, 0, sizeof (tBTM_INQUIRY_VAR_ST));
1371 btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1374 /*********************************************************************************
1376 ** Function btm_inq_stop_on_ssp
1378 ** Description This function is called on incoming SSP
1382 *******************************************************************************/
1383 void btm_inq_stop_on_ssp(void)
1385 UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE);
1387 #if (BTM_INQ_DEBUG == TRUE)
1388 BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d",
1389 btm_cb.btm_inq_vars.no_inc_ssp, btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1391 if (btm_cb.btm_inq_vars.no_inc_ssp)
1393 if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE)
1395 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
1397 BTM_CancelPeriodicInquiry();
1399 else if (btm_cb.btm_inq_vars.inq_active & normal_active)
1401 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1402 btsnd_hcic_inq_cancel();
1405 /* do not allow inquiry to start */
1406 btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1410 /*********************************************************************************
1412 ** Function btm_inq_clear_ssp
1414 ** Description This function is called when pairing_state becomes idle
1418 *******************************************************************************/
1419 void btm_inq_clear_ssp(void)
1421 btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1424 /*********************************************************************************
1426 ** Function btm_clr_inq_db
1428 ** Description This function is called to clear out a device or all devices
1429 ** from the inquiry database.
1431 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1432 ** (NULL clears all entries)
1436 *******************************************************************************/
1437 void btm_clr_inq_db (BD_ADDR p_bda)
1439 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1440 tINQ_DB_ENT *p_ent = p_inq->inq_db;
1443 #if (BTM_INQ_DEBUG == TRUE)
1444 BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d",
1445 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1447 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1451 /* If this is the specified BD_ADDR or clearing all devices */
1452 if (p_bda == NULL ||
1453 (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1455 p_ent->in_use = FALSE;
1459 #if (BTM_INQ_DEBUG == TRUE)
1460 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d",
1461 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1466 /*******************************************************************************
1468 ** Function btm_clr_inq_result_flt
1470 ** Description This function looks through the bdaddr database for a match
1471 ** based on Bluetooth Device Address
1473 ** Returns TRUE if found, else FALSE (new entry)
1475 *******************************************************************************/
1476 static void btm_clr_inq_result_flt (void)
1478 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1482 GKI_freebuf(p_inq->p_bd_db);
1483 p_inq->p_bd_db = NULL;
1485 p_inq->num_bd_entries = 0;
1486 p_inq->max_bd_entries = 0;
1489 /*******************************************************************************
1491 ** Function btm_inq_find_bdaddr
1493 ** Description This function looks through the bdaddr database for a match
1494 ** based on Bluetooth Device Address
1496 ** Returns TRUE if found, else FALSE (new entry)
1498 *******************************************************************************/
1499 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1501 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1502 tINQ_BDADDR *p_db = &p_inq->p_bd_db[0];
1505 /* Don't bother searching, database doesn't exist or periodic mode */
1506 if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db)
1509 for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++)
1511 if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1512 && p_db->inq_count == p_inq->inq_counter)
1516 if (xx < p_inq->max_bd_entries)
1518 p_db->inq_count = p_inq->inq_counter;
1519 memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1520 p_inq->num_bd_entries++;
1523 /* If here, New Entry */
1527 /*******************************************************************************
1529 ** Function btm_inq_db_find
1531 ** Description This function looks through the inquiry database for a match
1532 ** based on Bluetooth Device Address
1534 ** Returns pointer to entry, or NULL if not found
1536 *******************************************************************************/
1537 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1540 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1542 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1544 if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1548 /* If here, not found */
1553 /*******************************************************************************
1555 ** Function btm_inq_db_new
1557 ** Description This function looks through the inquiry database for an unused
1558 ** entry. If no entry is free, it allocates the oldest entry.
1560 ** Returns pointer to entry
1562 *******************************************************************************/
1563 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1566 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1567 tINQ_DB_ENT *p_old = btm_cb.btm_inq_vars.inq_db;
1568 UINT32 ot = 0xFFFFFFFF;
1570 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1574 memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1575 memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1576 p_ent->in_use = TRUE;
1581 if (p_ent->time_of_resp < ot)
1584 ot = p_ent->time_of_resp;
1588 /* If here, no free entry found. Return the oldest. */
1590 memset (p_old, 0, sizeof (tINQ_DB_ENT));
1591 memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1592 p_old->in_use = TRUE;
1598 /*******************************************************************************
1600 ** Function btm_set_inq_event_filter
1602 ** Description This function is called to set the inquiry event filter.
1603 ** It is called by either internally, or by the external API function
1604 ** (BTM_SetInqEventFilter). It is used internally as part of the
1605 ** inquiry processing.
1608 ** filter_cond_type - this is the type of inquiry filter to apply:
1609 ** BTM_FILTER_COND_DEVICE_CLASS,
1610 ** BTM_FILTER_COND_BD_ADDR, or
1611 ** BTM_CLR_INQUIRY_FILTER
1613 ** p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1614 ** filter_cond_type (See section 4.7.3 of Core Spec 1.0b).
1616 ** Returns BTM_CMD_STARTED if successfully initiated
1617 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
1618 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
1620 *******************************************************************************/
1621 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1622 tBTM_INQ_FILT_COND *p_filt_cond)
1624 UINT8 condition_length = DEV_CLASS_LEN * 2;
1625 UINT8 condition_buf[DEV_CLASS_LEN * 2];
1626 UINT8 *p_cond = condition_buf; /* points to the condition to pass to HCI */
1628 #if (BTM_INQ_DEBUG == TRUE)
1629 BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
1631 BTM_TRACE_DEBUG (" condition [%02x%02x%02x %02x%02x%02x]",
1632 p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1633 p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1636 /* Load the correct filter condition to pass to the lower layer */
1637 switch (filter_cond_type)
1639 case BTM_FILTER_COND_DEVICE_CLASS:
1640 /* copy the device class and device class fields into contiguous memory to send to HCI */
1641 memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1642 memcpy (&condition_buf[DEV_CLASS_LEN],
1643 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1645 /* condition length should already be set as the default */
1648 case BTM_FILTER_COND_BD_ADDR:
1649 p_cond = p_filt_cond->bdaddr_cond;
1651 /* condition length should already be set as the default */
1654 case BTM_CLR_INQUIRY_FILTER:
1655 condition_length = 0;
1659 return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1662 btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1664 /* Filter the inquiry results for the specified condition type and value */
1665 if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1666 p_cond, condition_length))
1668 return (BTM_CMD_STARTED);
1670 return (BTM_NO_RESOURCES);
1674 /*******************************************************************************
1676 ** Function btm_event_filter_complete
1678 ** Description This function is called when a set event filter has completed.
1679 ** Note: This routine currently only handles inquiry filters.
1680 ** Connection filters are ignored for now.
1684 *******************************************************************************/
1685 void btm_event_filter_complete (UINT8 *p)
1689 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1690 tBTM_CMPL_CB *p_cb = p_inq->p_inqfilter_cmpl_cb;
1692 #if (BTM_INQ_DEBUG == TRUE)
1693 BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d",
1694 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1696 /* If the filter complete event is from an old or cancelled request, ignore it */
1697 if(p_inq->pending_filt_complete_event)
1699 p_inq->pending_filt_complete_event--;
1703 /* Only process the inquiry filter; Ignore the connection filter until it
1704 is used by the upper layers */
1705 if (p_inq->inqfilt_active == TRUE )
1707 /* Extract the returned status from the buffer */
1708 STREAM_TO_UINT8 (hci_status, p);
1709 if (hci_status != HCI_SUCCESS)
1711 /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1712 BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)", hci_status);
1713 status = BTM_ERR_PROCESSING;
1716 status = BTM_SUCCESS;
1718 /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1719 callback function to notify the initiator that it has completed */
1720 if (p_inq->state == BTM_INQ_INACTIVE_STATE)
1722 p_inq->inqfilt_active = FALSE;
1726 else /* An inquiry is active (the set filter command was internally generated),
1727 process the next state of the process (Set a new filter or start the inquiry). */
1729 if(status != BTM_SUCCESS)
1731 /* Process the inquiry complete (Error Status) */
1732 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1734 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1735 p_inq->inqfilt_active = FALSE;
1736 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1737 p_inq->state = BTM_INQ_INACTIVE_STATE;
1742 /* Check to see if a new filter needs to be set up */
1743 if (p_inq->state == BTM_INQ_CLR_FILT_STATE)
1745 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED)
1747 p_inq->state = BTM_INQ_SET_FILT_STATE;
1749 else /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1751 p_inq->inqfilt_active = FALSE;
1753 /* Process the inquiry complete (Error Status) */
1754 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1757 else /* Initiate the Inquiry or Periodic Inquiry */
1759 p_inq->state = BTM_INQ_ACTIVE_STATE;
1760 p_inq->inqfilt_active = FALSE;
1761 btm_initiate_inquiry (p_inq);
1768 /*******************************************************************************
1770 ** Function btm_initiate_inquiry
1772 ** Description This function is called to start an inquiry or periodic inquiry
1773 ** upon completion of the setting and/or clearing of the inquiry filter.
1775 ** Inputs: p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1776 ** mode - GENERAL or LIMITED inquiry
1777 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1778 ** max_resps - maximum amount of devices to search for before ending the inquiry
1779 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1780 ** BTM_FILTER_COND_BD_ADDR
1781 ** filter_cond - value for the filter (based on filter_cond_type)
1783 ** Returns If an error occurs the initiator's callback is called with the error status.
1785 *******************************************************************************/
1786 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1789 tBTM_INQ_PARMS *p_inqparms = &p_inq->inqparms;
1791 #if (BTM_INQ_DEBUG == TRUE)
1792 BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d",
1793 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1795 btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1797 if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE)
1799 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1803 /* Make sure the number of responses doesn't overflow the database configuration */
1804 p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1806 lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1808 if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
1810 if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1811 p_inq->per_min_delay,
1812 *lap, p_inqparms->duration,
1813 p_inqparms->max_resps))
1814 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1818 btm_clr_inq_result_flt();
1820 /* Allocate memory to hold bd_addrs responding */
1821 if ((p_inq->p_bd_db = (tINQ_BDADDR *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
1823 p_inq->max_bd_entries = (UINT16)(GKI_MAX_BUF_SIZE / sizeof(tINQ_BDADDR));
1824 memset(p_inq->p_bd_db, 0, GKI_MAX_BUF_SIZE);
1825 /* BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1826 p_inq->max_bd_entries); */
1829 if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0))
1830 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1834 /*******************************************************************************
1836 ** Function btm_process_inq_results
1838 ** Description This function is called when inquiry results are received from
1839 ** the device. It updates the inquiry database. If the inquiry
1840 ** database is full, the oldest entry is discarded.
1842 ** Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
1843 ** BTM_INQ_RESULT_WITH_RSSI
1844 ** BTM_INQ_RESULT_EXTENDED
1848 *******************************************************************************/
1849 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1854 tBTM_INQ_RESULTS *p_cur=NULL;
1855 BOOLEAN is_new = TRUE;
1856 BOOLEAN update = FALSE;
1858 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1859 tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1860 UINT8 page_scan_rep_mode = 0;
1861 UINT8 page_scan_per_mode = 0;
1862 UINT8 page_scan_mode = 0;
1865 UINT16 clock_offset;
1866 UINT8 *p_eir_data = NULL;
1868 #if (BTM_INQ_DEBUG == TRUE)
1869 BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
1870 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1872 /* Only process the results if the BR inquiry is still active */
1873 if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
1876 STREAM_TO_UINT8 (num_resp, p);
1878 for (xx = 0; xx < num_resp; xx++)
1881 /* Extract inquiry results */
1882 STREAM_TO_BDADDR (bda, p);
1883 STREAM_TO_UINT8 (page_scan_rep_mode, p);
1884 STREAM_TO_UINT8 (page_scan_per_mode, p);
1886 if (inq_res_mode == BTM_INQ_RESULT_STANDARD)
1888 STREAM_TO_UINT8(page_scan_mode, p);
1891 STREAM_TO_DEVCLASS (dc, p);
1892 STREAM_TO_UINT16 (clock_offset, p);
1893 if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
1895 STREAM_TO_UINT8(rssi, p);
1898 p_i = btm_inq_db_find (bda);
1900 /* Only process the num_resp is smaller than max_resps.
1901 If results are queued to BTU task while canceling inquiry,
1902 or when more than one result is in this response, > max_resp
1903 responses could be processed which can confuse some apps
1905 if (p_inq->inqparms.max_resps &&
1906 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1907 #if BLE_INCLUDED == TRUE
1908 /* new device response */
1910 /* exisiting device with BR/EDR info */
1911 (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1917 /* BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring"); */
1921 /* Check if this address has already been processed for this inquiry */
1922 if (btm_inq_find_bdaddr(bda))
1924 /* BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]",
1925 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);*/
1926 /* By default suppose no update needed */
1927 i_rssi = (INT8)rssi;
1929 /* If this new RSSI is higher than the last one */
1930 if(p_inq->inqparms.report_dup && (rssi != 0) &&
1931 p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1932 #if BLE_INCLUDED == TRUE
1933 /* BR/EDR inquiry information update */
1934 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1938 p_cur = &p_i->inq_info.results;
1939 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);
1940 p_cur->rssi = i_rssi;
1943 /* If we received a second Extended Inq Event for an already */
1944 /* discovered device, this is because for the first one EIR was not received */
1945 else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i))
1947 p_cur = &p_i->inq_info.results;
1950 /* If no update needed continue with next response (if any) */
1955 /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
1958 p_i = btm_inq_db_new (bda);
1962 /* If an entry for the device already exists, overwrite it ONLY if it is from
1963 a previous inquiry. (Ignore it if it is a duplicate response from the same
1966 else if (p_i->inq_count == p_inq->inq_counter
1967 #if (BLE_INCLUDED == TRUE )
1968 && (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)
1973 /* keep updating RSSI to have latest value */
1974 if( inq_res_mode != BTM_INQ_RESULT_STANDARD )
1975 p_i->inq_info.results.rssi = (INT8)rssi;
1977 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1982 p_cur = &p_i->inq_info.results;
1983 p_cur->page_scan_rep_mode = page_scan_rep_mode;
1984 p_cur->page_scan_per_mode = page_scan_per_mode;
1985 p_cur->page_scan_mode = page_scan_mode;
1986 p_cur->dev_class[0] = dc[0];
1987 p_cur->dev_class[1] = dc[1];
1988 p_cur->dev_class[2] = dc[2];
1989 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
1991 p_i->time_of_resp = GKI_get_os_tick_count();
1993 if (p_i->inq_count != p_inq->inq_counter)
1994 p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
1996 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
1997 p_cur->inq_result_type = BTM_INQ_RESULT_BR;
1998 if (p_i->inq_count != p_inq->inq_counter)
2000 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
2001 p_i->scan_rsp = FALSE;
2004 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
2006 p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
2008 /* If the number of responses found and not unlimited, issue a cancel inquiry */
2009 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
2010 p_inq->inqparms.max_resps &&
2011 p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
2012 #if BLE_INCLUDED == TRUE
2013 /* BLE scanning is active and received adv */
2014 && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
2015 p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
2016 (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
2020 /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
2021 btsnd_hcic_inq_cancel();
2023 #if BLE_INCLUDED == TRUE
2024 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
2025 btm_ble_stop_inquiry();
2027 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2029 /* Initialize flag to FALSE. This flag is set/used by application */
2030 p_i->inq_info.appl_knows_rem_name = FALSE;
2033 if (is_new || update)
2035 if( inq_res_mode == BTM_INQ_RESULT_EXTENDED )
2037 memset( p_cur->eir_uuid, 0,
2038 BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS/8));
2039 /* set bit map of UUID list from received EIR */
2040 btm_set_eir_uuid( p, p_cur );
2046 /* If a callback is registered, call it with the results */
2047 if (p_inq_results_cb)
2048 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2053 /*******************************************************************************
2055 ** Function btm_sort_inq_result
2057 ** Description This function is called when inquiry complete is received
2058 ** from the device to sort inquiry results based on rssi.
2062 *******************************************************************************/
2063 void btm_sort_inq_result(void)
2065 UINT8 xx, yy, num_resp;
2066 tINQ_DB_ENT *p_tmp = NULL;
2067 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
2068 tINQ_DB_ENT *p_next = btm_cb.btm_inq_vars.inq_db+1;
2071 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp<BTM_INQ_DB_SIZE)?
2072 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp: BTM_INQ_DB_SIZE;
2074 if((p_tmp = (tINQ_DB_ENT *)GKI_getbuf(sizeof(tINQ_DB_ENT))) != NULL)
2076 size = sizeof(tINQ_DB_ENT);
2077 for(xx = 0; xx < num_resp-1; xx++, p_ent++)
2079 for(yy = xx+1, p_next = p_ent+1; yy < num_resp; yy++, p_next++)
2081 if(p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi)
2083 memcpy (p_tmp, p_next, size);
2084 memcpy (p_next, p_ent, size);
2085 memcpy (p_ent, p_tmp, size);
2094 /*******************************************************************************
2096 ** Function btm_process_inq_complete
2098 ** Description This function is called when inquiry complete is received
2099 ** from the device. Call the callback if not in periodic inquiry
2100 ** mode AND it is not NULL (The caller wants the event).
2102 ** The callback pass back the status and the number of responses
2106 *******************************************************************************/
2107 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2109 tBTM_CMPL_CB *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2110 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2112 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2113 /* inquiry inactive case happens when inquiry is cancelled.
2114 Make mode 0 for no further inquiries from the current inquiry process
2116 if(status!=HCI_SUCCESS || p_inq->next_state==BTM_FINISH || !p_inq->inq_active)
2118 /* re-initialize for next inquiry request */
2119 p_inq->next_state=BTM_BR_ONE;
2120 /* make the mode 0 here */
2121 p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2126 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2127 p_inq->inqparms.mode &= ~(mode);
2130 if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active)
2132 /*end of LE observe*/
2133 p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2134 p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2135 p_inq->scan_type=INQ_NONE;
2139 #if (BTM_INQ_DEBUG == TRUE)
2140 BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d",
2141 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2143 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2144 /* Ignore any stray or late complete messages if the inquiry is not active */
2145 if (p_inq->inq_active)
2147 p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2149 /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2150 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)
2152 #if BLE_INCLUDED == TRUE
2153 btm_clear_all_pending_le_entry();
2155 p_inq->state = BTM_INQ_INACTIVE_STATE;
2157 /* Increment so the start of a next inquiry has a new count */
2158 p_inq->inq_counter++;
2160 btm_clr_inq_result_flt();
2162 if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2163 controller_get_interface()->supports_rssi_with_inquiry_results())
2165 btm_sort_inq_result();
2168 /* Clear the results callback if set */
2169 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2170 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2171 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2173 /* If we have a callback registered for inquiry complete, call it */
2174 BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d",
2175 p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2178 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2180 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2181 if(p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))
2183 /* make inquiry inactive for next iteration */
2184 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2185 /* call the inquiry again */
2186 BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
2190 if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
2192 p_inq->scan_type = INQ_NONE;
2193 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2194 /* check if the LE observe is pending */
2195 if(p_inq->p_inq_ble_results_cb != NULL)
2197 BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2198 BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2202 #if (BTM_INQ_DEBUG == TRUE)
2203 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d",
2204 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2208 /*******************************************************************************
2210 ** Function btm_process_cancel_complete
2212 ** Description This function is called when inquiry cancel complete is received
2213 ** from the device.This function will also call the btm_process_inq_complete
2214 ** This function is needed to differentiate a cancel_cmpl_evt from the
2219 *******************************************************************************/
2220 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2222 btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2223 btm_process_inq_complete(status, mode);
2225 /*******************************************************************************
2227 ** Function btm_initiate_rem_name
2229 ** Description This function looks initiates a remote name request. It is called
2230 ** either by GAP or by the API call BTM_ReadRemoteDeviceName.
2232 ** Input Params: p_cur - pointer to an inquiry result structure (NULL if nonexistent)
2233 ** p_cb - callback function called when BTM_CMD_STARTED
2235 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2239 ** BTM_CMD_STARTED is returned if the request was sent to HCI.
2240 ** BTM_BUSY if already in progress
2241 ** BTM_NO_RESOURCES if could not allocate resources to start the command
2242 ** BTM_WRONG_MODE if the device is not up.
2244 *******************************************************************************/
2245 tBTM_STATUS btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2246 UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2248 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2252 /*** Make sure the device is ready ***/
2253 if (!BTM_IsDeviceUp())
2254 return (BTM_WRONG_MODE);
2257 if (origin == BTM_RMT_NAME_SEC)
2259 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2260 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2262 return BTM_CMD_STARTED;
2264 return BTM_NO_RESOURCES;
2266 /* Make sure there are no two remote name requests from external API in progress */
2267 else if (origin == BTM_RMT_NAME_EXT)
2269 if (p_inq->remname_active)
2275 /* If there is no remote name request running,call the callback function and start timer */
2276 p_inq->p_remname_cmpl_cb = p_cb;
2277 memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2278 btu_start_timer (&p_inq->rmt_name_timer_ent,
2279 BTU_TTYPE_BTM_RMT_NAME,
2282 /* If the database entry exists for the device, use its clock offset */
2285 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2286 p_cur->results.page_scan_rep_mode,
2287 p_cur->results.page_scan_mode,
2288 (UINT16)(p_cur->results.clock_offset |
2289 BTM_CLOCK_OFFSET_VALID));
2291 else /* Otherwise use defaults and mark the clock offset as invalid */
2293 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2294 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2298 p_inq->remname_active = TRUE;
2299 return BTM_CMD_STARTED;
2302 return BTM_NO_RESOURCES;
2307 return BTM_ILLEGAL_VALUE;
2311 /*******************************************************************************
2313 ** Function btm_process_remote_name
2315 ** Description This function is called when a remote name is received from
2316 ** the device. If remote names are cached, it updates the inquiry
2321 *******************************************************************************/
2322 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2324 tBTM_REMOTE_DEV_NAME rem_name;
2325 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2326 tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
2329 UINT16 temp_evt_len;
2333 BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x",bda[0], bda[1],
2338 BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x",p_inq->remname_bda[0], p_inq->remname_bda[1],
2339 p_inq->remname_bda[2], p_inq->remname_bda[3],
2340 p_inq->remname_bda[4], p_inq->remname_bda[5]);
2344 /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2345 if ((p_inq->remname_active ==TRUE)&&
2347 (memcmp(bda, p_inq->remname_bda,BD_ADDR_LEN)==0)) || bda == NULL))
2350 #if BLE_INCLUDED == TRUE
2351 if (BTM_UseLeLink(p_inq->remname_bda))
2353 if (hci_status == HCI_ERR_UNSPECIFIED)
2354 btm_ble_cancel_remote_name(p_inq->remname_bda);
2357 btu_stop_timer (&p_inq->rmt_name_timer_ent);
2358 p_inq->remname_active = FALSE;
2359 /* Clean up and return the status if the command was not successful */
2360 /* Note: If part of the inquiry, the name is not stored, and the */
2361 /* inquiry complete callback is called. */
2363 if (hci_status == HCI_SUCCESS)
2365 /* Copy the name from the data stream into the return structure */
2366 /* Note that even if it is not being returned, it is used as a */
2367 /* temporary buffer. */
2368 p_n1 = (UINT8 *)rem_name.remote_bd_name;
2369 rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2370 rem_name.remote_bd_name[rem_name.length] = 0;
2371 rem_name.status = BTM_SUCCESS;
2372 temp_evt_len = rem_name.length;
2374 while (temp_evt_len > 0)
2379 rem_name.remote_bd_name[rem_name.length] = 0;
2383 /* If processing a stand alone remote name then report the error in the callback */
2386 rem_name.status = BTM_BAD_VALUE_RET;
2387 rem_name.length = 0;
2388 rem_name.remote_bd_name[0] = 0;
2390 /* Reset the remote BAD to zero and call callback if possible */
2391 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2393 p_inq->p_remname_cmpl_cb = NULL;
2395 (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2399 /*******************************************************************************
2401 ** Function btm_inq_rmt_name_failed
2403 ** Description This function is if timeout expires while getting remote
2404 ** name. This is done for devices that incorrectly do not
2405 ** report operation failure
2409 *******************************************************************************/
2410 void btm_inq_rmt_name_failed (void)
2412 BTM_TRACE_ERROR ("btm_inq_rmt_name_failed() remname_active=%d", btm_cb.btm_inq_vars.remname_active);
2414 if (btm_cb.btm_inq_vars.remname_active)
2415 btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2417 btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2419 btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2421 /*******************************************************************************
2423 ** Function btm_read_linq_tx_power_complete
2425 ** Description read inquiry tx power level complete callback function.
2429 *******************************************************************************/
2430 void btm_read_linq_tx_power_complete(UINT8 *p)
2432 tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2433 tBTM_INQ_TXPWR_RESULTS results;
2435 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2436 /* If there was a callback registered for read inq tx power, call it */
2437 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2441 STREAM_TO_UINT8 (results.hci_status, p);
2443 if (results.hci_status == HCI_SUCCESS)
2445 results.status = BTM_SUCCESS;
2447 STREAM_TO_UINT8 (results.tx_power, p);
2448 BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x",
2449 results.tx_power, results.hci_status);
2452 results.status = BTM_ERR_PROCESSING;
2458 /*******************************************************************************
2460 ** Function BTM_WriteEIR
2462 ** Description This function is called to write EIR data to controller.
2464 ** Parameters p_buff - allocated HCI command buffer including extended
2465 ** inquriry response
2467 ** Returns BTM_SUCCESS - if successful
2468 ** BTM_MODE_UNSUPPORTED - if local device cannot support it
2470 *******************************************************************************/
2471 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2473 if (controller_get_interface()->supports_extended_inquiry_response())
2475 BTM_TRACE_API("Write Extended Inquiry Response to controller");
2476 btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2481 GKI_freebuf(p_buff);
2482 return BTM_MODE_UNSUPPORTED;
2486 /*******************************************************************************
2488 ** Function BTM_CheckEirData
2490 ** Description This function is called to get EIR data from significant part.
2492 ** Parameters p_eir - pointer of EIR significant part
2493 ** type - finding EIR data type
2494 ** p_length - return the length of EIR data not including type
2496 ** Returns pointer of EIR data
2498 *******************************************************************************/
2499 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2504 BTM_TRACE_API("BTM_CheckEirData type=0x%02X", type);
2506 STREAM_TO_UINT8(length, p);
2507 while( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN))
2509 STREAM_TO_UINT8(eir_type, p);
2510 if( eir_type == type )
2512 /* length doesn't include itself */
2513 *p_length = length - 1; /* minus the length of type */
2516 p += length - 1; /* skip the length of data */
2517 STREAM_TO_UINT8(length, p);
2524 /*******************************************************************************
2526 ** Function btm_convert_uuid_to_eir_service
2528 ** Description This function is called to get the bit position of UUID.
2530 ** Parameters uuid16 - UUID 16-bit
2532 ** Returns BTM EIR service ID if found
2533 ** BTM_EIR_MAX_SERVICES - if not found
2535 *******************************************************************************/
2536 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2540 for( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ )
2542 if( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx])
2547 return BTM_EIR_MAX_SERVICES;
2550 /*******************************************************************************
2552 ** Function BTM_HasEirService
2554 ** Description This function is called to know if UUID in bit map of UUID.
2556 ** Parameters p_eir_uuid - bit map of UUID list
2557 ** uuid16 - UUID 16-bit
2559 ** Returns TRUE - if found
2560 ** FALSE - if not found
2562 *******************************************************************************/
2563 BOOLEAN BTM_HasEirService( 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 return( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2574 /*******************************************************************************
2576 ** Function BTM_HasInquiryEirService
2578 ** Description This function is called to know if UUID in bit map of UUID list.
2580 ** Parameters p_results - inquiry results
2581 ** uuid16 - UUID 16-bit
2583 ** Returns BTM_EIR_FOUND - if found
2584 ** BTM_EIR_NOT_FOUND - if not found and it is complete list
2585 ** BTM_EIR_UNKNOWN - if not found and it is not complete list
2587 *******************************************************************************/
2588 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2590 if( BTM_HasEirService( p_results->eir_uuid, uuid16 ))
2592 return BTM_EIR_FOUND;
2594 else if( p_results->eir_complete_list )
2596 return BTM_EIR_NOT_FOUND;
2599 return BTM_EIR_UNKNOWN;
2602 /*******************************************************************************
2604 ** Function BTM_AddEirService
2606 ** Description This function is called to add a service in bit map of UUID list.
2608 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2609 ** uuid16 - UUID 16-bit
2613 *******************************************************************************/
2614 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2618 service_id = btm_convert_uuid_to_eir_service(uuid16);
2619 if( service_id < BTM_EIR_MAX_SERVICES )
2620 BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2623 /*******************************************************************************
2625 ** Function BTM_RemoveEirService
2627 ** Description This function is called to remove a service in bit map of UUID list.
2629 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2630 ** uuid16 - UUID 16-bit
2634 *******************************************************************************/
2635 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2639 service_id = btm_convert_uuid_to_eir_service(uuid16);
2640 if( service_id < BTM_EIR_MAX_SERVICES )
2641 BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2644 /*******************************************************************************
2646 ** Function BTM_GetEirSupportedServices
2648 ** Description This function is called to get UUID list from bit map of UUID list.
2650 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
2651 ** p - reference of current pointer of EIR
2652 ** max_num_uuid16 - max number of UUID can be written in EIR
2653 ** num_uuid16 - number of UUID have been written in EIR
2655 ** Returns BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2656 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2658 *******************************************************************************/
2659 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid, UINT8 **p,
2660 UINT8 max_num_uuid16, UINT8 *p_num_uuid16)
2662 UINT8 service_index;
2666 for(service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++)
2668 if( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index ))
2670 if( *p_num_uuid16 < max_num_uuid16 )
2672 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2675 /* if max number of UUIDs are stored and found one more */
2678 return BTM_EIR_MORE_16BITS_UUID_TYPE;
2682 return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2685 /*******************************************************************************
2687 ** Function BTM_GetEirUuidList
2689 ** Description This function parses EIR and returns UUID list.
2691 ** Parameters p_eir - EIR
2692 ** uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2693 ** p_num_uuid - return number of UUID in found list
2694 ** p_uuid_list - return UUID list
2695 ** max_num_uuid - maximum number of UUID to be returned
2697 ** Returns 0 - if not found
2698 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2699 ** BTM_EIR_MORE_16BITS_UUID_TYPE
2700 ** BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2701 ** BTM_EIR_MORE_32BITS_UUID_TYPE
2702 ** BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2703 ** BTM_EIR_MORE_128BITS_UUID_TYPE
2705 *******************************************************************************/
2706 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2707 UINT8 *p_uuid_list, UINT8 max_num_uuid)
2712 UINT16 *p_uuid16 = (UINT16 *)p_uuid_list;
2713 UINT32 *p_uuid32 = (UINT32 *)p_uuid_list;
2714 char buff[LEN_UUID_128 * 2 + 1];
2716 p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2717 if( p_uuid_data == NULL )
2722 if( *p_num_uuid > max_num_uuid )
2724 BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d",
2725 *p_num_uuid, max_num_uuid );
2726 *p_num_uuid = max_num_uuid;
2729 BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d", type, *p_num_uuid );
2731 if( uuid_size == LEN_UUID_16 )
2733 for( yy = 0; yy < *p_num_uuid; yy++ )
2735 STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2736 BTM_TRACE_DEBUG(" 0x%04X", *(p_uuid16 + yy));
2739 else if( uuid_size == LEN_UUID_32 )
2741 for( yy = 0; yy < *p_num_uuid; yy++ )
2743 STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2744 BTM_TRACE_DEBUG(" 0x%08X", *(p_uuid32 + yy));
2747 else if( uuid_size == LEN_UUID_128 )
2749 for( yy = 0; yy < *p_num_uuid; yy++ )
2751 STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2752 for( xx = 0; xx < LEN_UUID_128; xx++ )
2753 sprintf(buff + xx*2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2754 BTM_TRACE_DEBUG(" 0x%s", buff);
2762 /*******************************************************************************
2764 ** Function btm_eir_get_uuid_list
2766 ** Description This function searches UUID list in EIR.
2768 ** Parameters p_eir - address of EIR
2769 ** uuid_size - size of UUID to find
2770 ** p_num_uuid - number of UUIDs found
2771 ** p_uuid_list_type - EIR data type
2773 ** Returns NULL - if UUID list with uuid_size is not found
2774 ** beginning of UUID list in EIR - otherwise
2776 *******************************************************************************/
2777 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2778 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2781 UINT8 complete_type, more_type;
2787 complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2788 more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2791 complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2792 more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
2795 complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2796 more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
2804 p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2805 if(p_uuid_data == NULL)
2807 p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2808 *p_uuid_list_type = more_type;
2812 *p_uuid_list_type = complete_type;
2815 *p_num_uuid = uuid_len / uuid_size;
2819 /*******************************************************************************
2821 ** Function btm_convert_uuid_to_uuid16
2823 ** Description This function converts UUID to UUID 16-bit.
2825 ** Parameters p_uuid - address of UUID
2826 ** uuid_size - size of UUID
2828 ** Returns 0 - if UUID cannot be converted to UUID 16-bit
2829 ** UUID 16-bit - otherwise
2831 *******************************************************************************/
2832 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2834 static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2835 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2838 BOOLEAN is_base_uuid;
2844 STREAM_TO_UINT16 (uuid16, p_uuid);
2847 STREAM_TO_UINT32 (uuid32, p_uuid);
2848 if (uuid32 < 0x10000)
2849 uuid16 = (UINT16) uuid32;
2852 /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2853 is_base_uuid = TRUE;
2854 for (xx = 0; xx < LEN_UUID_128 - 4; xx++)
2856 if (p_uuid[xx] != base_uuid[xx])
2858 is_base_uuid = FALSE;
2864 if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0))
2866 p_uuid += (LEN_UUID_128 - 4);
2867 STREAM_TO_UINT16(uuid16, p_uuid);
2872 BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size");
2879 /*******************************************************************************
2881 ** Function btm_set_eir_uuid
2883 ** Description This function is called to store received UUID into inquiry result.
2885 ** Parameters p_eir - pointer of EIR significant part
2886 ** p_results - pointer of inquiry result
2890 *******************************************************************************/
2891 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2897 UINT8 type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2899 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2901 if(type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE)
2903 p_results->eir_complete_list = TRUE;
2907 p_results->eir_complete_list = FALSE;
2910 BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X", p_results->eir_complete_list);
2914 for( yy = 0; yy < num_uuid; yy++ )
2916 STREAM_TO_UINT16(uuid16, p_uuid_data);
2917 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2921 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2924 for( yy = 0; yy < num_uuid; yy++ )
2926 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2927 p_uuid_data += LEN_UUID_32;
2929 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2933 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2936 for( yy = 0; yy < num_uuid; yy++ )
2938 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2939 p_uuid_data += LEN_UUID_128;
2941 BTM_AddEirService( p_results->eir_uuid, uuid16 );