]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/stack/btm/btm_inq.c
Merge branch 'bugfix/spiram_malloc_reserve_internal_fragments' into 'master'
[esp-idf] / components / bt / bluedroid / stack / btm / btm_inq.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 /******************************************************************************
20  *
21  *  This file contains functions that handle inquiries. These include
22  *  setting discoverable mode, controlling the mode of the Baseband, and
23  *  maintaining a small database of inquiry responses, with API for people
24  *  to browse it.
25  *
26  ******************************************************************************/
27
28 #include <string.h>
29 #include <stdio.h>
30 #include <stddef.h>
31
32 #include "osi/alarm.h"
33 #include "stack/bt_types.h"
34 #include "device/controller.h"
35 #include "stack/hcimsgs.h"
36 #include "stack/btu.h"
37 #include "stack/btm_api.h"
38 #include "btm_int.h"
39 #include "stack/hcidefs.h"
40 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
41 #include "stack/sdpdefs.h"
42 #endif
43
44 #define BTM_INQ_REPLY_TIMEOUT   3       /* 3 second timeout waiting for responses */
45
46 /* TRUE to enable DEBUG traces for btm_inq */
47 #ifndef BTM_INQ_DEBUG
48 #define BTM_INQ_DEBUG   FALSE
49 #endif
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};
55
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,
77     UUID_SERVCLASS_FAX,
78     UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
79     /*    UUID_SERVCLASS_WAP,                       */
80     /*    UUID_SERVCLASS_WAP_CLIENT,                */
81     UUID_SERVCLASS_PANU,
82     UUID_SERVCLASS_NAP,
83     UUID_SERVCLASS_GN,
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,                       */
105     UUID_SERVCLASS_SAP,
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
127 };
128 #else
129 static const UINT16 BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES];
130 #endif
131
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);
138
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 );
144
145 /*******************************************************************************
146 **
147 ** Function         BTM_SetDiscoverability
148 **
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.
153 **
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.
159 **
160 *******************************************************************************/
161 tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 interval)
162 {
163     UINT8        scan_mode = 0;
164     UINT16       service_class;
165     UINT8       *p_cod;
166     UINT8        major, minor;
167     DEV_CLASS    cod;
168     LAP          temp_lap[2];
169     BOOLEAN      is_limited;
170     BOOLEAN      cod_limited;
171
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))
176                 == BTM_SUCCESS) {
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);
179         }
180     }
181     inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
182 #endif
183
184     /*** Check mode parameter ***/
185     if (inq_mode > BTM_MAX_DISCOVERABLE) {
186         return (BTM_ILLEGAL_VALUE);
187     }
188
189     /* Make sure the controller is active */
190     if (!controller_get_interface()->get_is_ready()) {
191         return (BTM_DEV_RESET);
192     }
193
194     /* If the window and/or interval is '0', set to default values */
195     if (!window) {
196         window = BTM_DEFAULT_DISC_WINDOW;
197     }
198
199     if (!interval) {
200         interval = BTM_DEFAULT_DISC_INTERVAL;
201     }
202
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);
205
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 ||
214                 window > interval) {
215             return (BTM_ILLEGAL_VALUE);
216         }
217     }
218
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);
225
226             if (!btsnd_hcic_write_cur_iac_lap (2, (LAP * const) temp_lap)) {
227                 return (BTM_NO_RESOURCES);    /* Cannot continue */
228             }
229         } else {
230             if (!btsnd_hcic_write_cur_iac_lap (1, (LAP * const) &general_inq_lap)) {
231                 return (BTM_NO_RESOURCES);    /* Cannot continue */
232             }
233         }
234
235         scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
236     }
237
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;
244         } else {
245             return (BTM_NO_RESOURCES);
246         }
247     }
248
249     if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK) {
250         scan_mode |= HCI_PAGE_SCAN_ENABLED;
251     }
252
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;
256     } else {
257         return (BTM_NO_RESOURCES);
258     }
259
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 );
268         if (is_limited) {
269             service_class |= BTM_COD_SERVICE_LMTD_DISCOVER;
270         } else {
271             service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER;
272         }
273
274         FIELDS_TO_COD(cod, minor, major, service_class);
275         (void) BTM_SetDeviceClass (cod);
276     }
277
278     return (BTM_SUCCESS);
279 }
280
281 /*******************************************************************************
282 **
283 ** Function         BTM_SetInquiryScanType
284 **
285 ** Description      This function is called to set the iquiry scan-type to
286 **                  standard or interlaced.
287 **
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.
291 **
292 *******************************************************************************/
293 tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type)
294 {
295
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);
299     }
300
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);
304     }
305
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;
311             } else {
312                 return (BTM_NO_RESOURCES);
313             }
314         } else {
315             return (BTM_WRONG_MODE);
316         }
317     }
318     return (BTM_SUCCESS);
319 }
320
321 /*******************************************************************************
322 **
323 ** Function         BTM_SetPageScanType
324 **
325 ** Description      This function is called to set the page scan-type to
326 **                  standard or interlaced.
327 **
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.
331 **
332 *******************************************************************************/
333 tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type)
334 {
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);
338     }
339
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);
343     }
344
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;
350             } else {
351                 return (BTM_NO_RESOURCES);
352             }
353         } else {
354             return (BTM_WRONG_MODE);
355         }
356     }
357     return (BTM_SUCCESS);
358 }
359
360
361 /*******************************************************************************
362 **
363 ** Function         BTM_SetInquiryMode
364 **
365 ** Description      This function is called to set standard or with RSSI
366 **                  mode of the inquiry for local device.
367 **
368 ** Output Params:   mode - standard, with RSSI, extended
369 **
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.
374 **
375 *******************************************************************************/
376 tBTM_STATUS BTM_SetInquiryMode (UINT8 mode)
377 {
378     const controller_t *controller = controller_get_interface();
379     BTM_TRACE_API ("BTM_SetInquiryMode\n");
380     if (mode == BTM_INQ_RESULT_STANDARD) {
381         /* mandatory mode */
382     } else if (mode == BTM_INQ_RESULT_WITH_RSSI) {
383         if (!controller->supports_rssi_with_inquiry_results()) {
384             return (BTM_MODE_UNSUPPORTED);
385         }
386     } else if (mode == BTM_INQ_RESULT_EXTENDED) {
387         if (!controller->supports_extended_inquiry_response()) {
388             return (BTM_MODE_UNSUPPORTED);
389         }
390     } else {
391         return (BTM_ILLEGAL_VALUE);
392     }
393
394     if (!BTM_IsDeviceUp()) {
395         return (BTM_WRONG_MODE);
396     }
397
398     if (!btsnd_hcic_write_inquiry_mode (mode)) {
399         return (BTM_NO_RESOURCES);
400     }
401
402     return (BTM_SUCCESS);
403 }
404
405 /*******************************************************************************
406 **
407 ** Function         BTM_ReadDiscoverability
408 **
409 ** Description      This function is called to read the current discoverability
410 **                  mode of the device.
411 **
412 ** Output Params:   p_window - current inquiry scan duration
413 **                  p_interval - current inquiry scan interval
414 **
415 ** Returns          BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
416 **                  BTM_GENERAL_DISCOVERABLE
417 **
418 *******************************************************************************/
419 UINT16 BTM_ReadDiscoverability (UINT16 *p_window, UINT16 *p_interval)
420 {
421     BTM_TRACE_API ("BTM_ReadDiscoverability\n");
422     if (p_window) {
423         *p_window = btm_cb.btm_inq_vars.inq_scan_window;
424     }
425
426     if (p_interval) {
427         *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
428     }
429
430     return (btm_cb.btm_inq_vars.discoverable_mode);
431 }
432
433
434 /*******************************************************************************
435 **
436 ** Function         BTM_SetPeriodicInquiryMode
437 **
438 ** Description      This function is called to set the device periodic inquiry mode.
439 **                  If the duration is zero, the periodic inquiry mode is cancelled.
440 **
441 **                  Note: We currently do not allow concurrent inquiry and periodic inquiry.
442 **
443 ** Parameters:      p_inqparms - pointer to the inquiry information
444 **                      mode - GENERAL or LIMITED inquiry
445 **                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
446 **                      max_resps - maximum amount of devices to search for before ending the inquiry
447 **                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
448 **                                         BTM_FILTER_COND_BD_ADDR
449 **                      filter_cond - value for the filter (based on filter_cond_type)
450 **
451 **                  max_delay - maximum amount of time between successive inquiries
452 **                  min_delay - minimum amount of time between successive inquiries
453 **                  p_results_cb - callback returning pointer to results (tBTM_INQ_RESULTS)
454 **
455 ** Returns          BTM_CMD_STARTED if successfully started
456 **                  BTM_ILLEGAL_VALUE if a bad parameter is detected
457 **                  BTM_NO_RESOURCES if could not allocate a message buffer
458 **                  BTM_SUCCESS - if cancelling the periodic inquiry
459 **                  BTM_BUSY - if an inquiry is already active
460 **                  BTM_WRONG_MODE if the device is not up.
461 **
462 *******************************************************************************/
463 tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_delay,
464                                         UINT16 min_delay, tBTM_INQ_RESULTS_CB *p_results_cb)
465 {
466     tBTM_STATUS  status;
467     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
468
469     BTM_TRACE_API ("BTM_SetPeriodicInquiryMode: mode: %d, dur: %d, rsps: %d, flt: %d, min: %d, max: %d\n",
470                    p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
471                    p_inqparms->filter_cond_type, min_delay, max_delay);
472
473     /*** Make sure the device is ready ***/
474     if (!BTM_IsDeviceUp()) {
475         return (BTM_WRONG_MODE);
476     }
477
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) {
481         return (BTM_BUSY);
482     }
483
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);
488     }
489
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*/
500     {
501         return (BTM_ILLEGAL_VALUE);
502     }
503
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;
510
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));
514
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
517        filter.
518     */
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;
524     }
525
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;
531
532     }
533
534     return (status);
535 }
536
537
538 /*******************************************************************************
539 **
540 ** Function         BTM_CancelPeriodicInquiry
541 **
542 ** Description      This function cancels a periodic inquiry
543 **
544 ** Returns
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.
548 **
549 *******************************************************************************/
550 tBTM_STATUS BTM_CancelPeriodicInquiry(void)
551 {
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");
555
556     /*** Make sure the device is ready ***/
557     if (!BTM_IsDeviceUp()) {
558         return (BTM_WRONG_MODE);
559     }
560
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;
565
566         if (!btsnd_hcic_exit_per_inq ()) {
567             status = BTM_NO_RESOURCES;
568         }
569
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++;
574         }
575
576         p_inq->inqfilt_active = FALSE;
577         p_inq->inq_counter++;
578     }
579
580     return (status);
581 }
582
583
584 /*******************************************************************************
585 **
586 ** Function         BTM_SetConnectability
587 **
588 ** Description      This function is called to set the device into or out of
589 **                  connectable mode. Discoverable mode means page scans enabled.
590 **
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.
595 **
596 *******************************************************************************/
597 tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 interval)
598 {
599     UINT8    scan_mode = 0;
600     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
601
602     BTM_TRACE_API ("BTM_SetConnectability\n");
603
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;
608         }
609         p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
610         p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
611     }
612     page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
613 #endif
614
615     /*** Check mode parameter ***/
616     if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE) {
617         return (BTM_ILLEGAL_VALUE);
618     }
619
620     /* Make sure the controller is active */
621     if (!controller_get_interface()->get_is_ready()) {
622         return (BTM_DEV_RESET);
623     }
624
625     /* If the window and/or interval is '0', set to default values */
626     if (!window) {
627         window = BTM_DEFAULT_CONN_WINDOW;
628     }
629
630     if (!interval) {
631         interval = BTM_DEFAULT_CONN_INTERVAL;
632     }
633
634     BTM_TRACE_API ("BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, interval 0x%04x\n",
635                    page_mode, window, interval);
636
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 ||
645                 window > interval) {
646             return (BTM_ILLEGAL_VALUE);
647         }
648
649         scan_mode |= HCI_PAGE_SCAN_ENABLED;
650     }
651
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);
658         }
659     }
660
661     /* Keep the inquiry scan as previouosly set */
662     if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK) {
663         scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
664     }
665
666     if (btsnd_hcic_write_scan_enable (scan_mode)) {
667         p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
668         p_inq->connectable_mode |= page_mode;
669
670         return (BTM_SUCCESS);
671     }
672
673     return (BTM_NO_RESOURCES);
674 }
675
676
677 /*******************************************************************************
678 **
679 ** Function         BTM_ReadConnectability
680 **
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
685 **
686 ** Returns          BTM_NON_CONNECTABLE or BTM_CONNECTABLE
687 **
688 *******************************************************************************/
689 UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval)
690 {
691     BTM_TRACE_API ("BTM_ReadConnectability\n");
692     if (p_window) {
693         *p_window = btm_cb.btm_inq_vars.page_scan_window;
694     }
695
696     if (p_interval) {
697         *p_interval = btm_cb.btm_inq_vars.page_scan_period;
698     }
699
700     return (btm_cb.btm_inq_vars.connectable_mode);
701 }
702
703
704
705 /*******************************************************************************
706 **
707 ** Function         BTM_IsInquiryActive
708 **
709 ** Description      This function returns a bit mask of the current inquiry state
710 **
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
715 **
716 *******************************************************************************/
717 UINT16 BTM_IsInquiryActive (void)
718 {
719     BTM_TRACE_API ("BTM_IsInquiryActive\n");
720
721     return (btm_cb.btm_inq_vars.inq_active);
722 }
723
724
725
726 /*******************************************************************************
727 **
728 ** Function         BTM_CancelInquiry
729 **
730 ** Description      This function cancels an inquiry if active
731 **
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.
735 **
736 *******************************************************************************/
737 tBTM_STATUS BTM_CancelInquiry(void)
738 {
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;
743 #endif
744     BTM_TRACE_API ("BTM_CancelInquiry called\n");
745
746     /*** Make sure the device is ready ***/
747     if (!BTM_IsDeviceUp()) {
748         return (BTM_WRONG_MODE);
749     }
750
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 */
758
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++;
764         }
765         /* Initiate the cancel inquiry */
766         else {
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)
770 #endif
771                ) {
772                 if (!btsnd_hcic_inq_cancel()) {
773                     status = BTM_NO_RESOURCES;
774                 }
775             }
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)
780 #endif
781                ) {
782                 btm_ble_stop_inquiry();
783             }
784 #endif
785         }
786
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);
790          */
791
792         p_inq->inq_counter++;
793         btm_clr_inq_result_flt();
794     }
795
796     return (status);
797 }
798
799
800 /*******************************************************************************
801 **
802 ** Function         BTM_StartInquiry
803 **
804 ** Description      This function is called to start an inquiry.
805 **
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)
813 **
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.
817 **
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.
827 **
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)
831 {
832     tBTM_STATUS  status = BTM_CMD_STARTED;
833     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
834
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);
838
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);
850         } else
851 #endif
852         {
853             return (BTM_BUSY);
854             BTM_TRACE_API("BTM_StartInquiry: return BUSY\n");
855         }
856     } else {
857         p_inq->scan_type = INQ_GENERAL;
858     }
859
860     /*** Make sure the device is ready ***/
861     if (!BTM_IsDeviceUp()) {
862         return (BTM_WRONG_MODE);
863     }
864
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
870 #endif
871        ) {
872         return (BTM_ILLEGAL_VALUE);
873     }
874
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;
878     }
879 #endif
880
881
882     /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
883     p_inq->inqparms = *p_inqparms;
884
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;
891
892     BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x\n", p_inq->inq_active);
893
894     /* interleave scan minimal conditions */
895 #if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE))
896
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;
902     } else {
903         BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x\n", p_inqparms->mode);
904         p_inq->next_state = BTM_NO_INTERLEAVING;
905     }
906 #endif
907
908
909
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)
916 #endif
917        )
918
919     {
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));
924 #endif
925         if (!controller_get_interface()->supports_ble()) {
926             p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
927             status = BTM_ILLEGAL_VALUE;
928         }
929         /* BLE for now does not support filter condition for inquiry */
930         else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
931                            p_inqparms->duration)) != BTM_CMD_STARTED) {
932             BTM_TRACE_ERROR("Err Starting LE Inquiry.\n");
933             p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
934         }
935 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
936         p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
937 #endif
938
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;
942         } else {
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;
946         }
947         /* reset next_state if status <> BTM_Started */
948         if (status != BTM_CMD_STARTED) {
949             p_inq->next_state = BTM_BR_ONE;
950         }
951
952         /* if interleave scan..return here */
953         return status;
954 #endif
955
956
957         BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x\n", p_inqparms->mode);
958     }
959 #endif /* end of BLE_INCLUDED */
960
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) {
963         return status;
964     }
965
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);
971 #endif
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
974            filter.
975         */
976         switch (p_inqparms->filter_cond_type) {
977         case BTM_CLR_INQUIRY_FILTER:
978             p_inq->state = BTM_INQ_SET_FILT_STATE;
979             break;
980
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 ????? */
988             break;
989
990         default:
991             return (BTM_ILLEGAL_VALUE);
992         }
993
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;
998         }
999
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;
1003         } else {
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;
1007         }
1008     }
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?
1012         */
1013         BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x\n", status);
1014         p_inq->next_state = BTM_BR_ONE;
1015     }
1016 #endif
1017
1018
1019     return (status);
1020 }
1021
1022
1023 /*******************************************************************************
1024 **
1025 ** Function         BTM_ReadRemoteDeviceName
1026 **
1027 ** Description      This function initiates a remote device HCI command to the
1028 **                  controller and calls the callback when the process has completed.
1029 **
1030 ** Input Params:    remote_bda      - device address of name to retrieve
1031 **                  p_cb            - callback function called when BTM_CMD_STARTED
1032 **                                    is returned.
1033 **                                    A pointer to tBTM_REMOTE_DEV_NAME is passed to the
1034 **                                    callback.
1035 **
1036 ** Returns
1037 **                  BTM_CMD_STARTED is returned if the request was successfully sent
1038 **                                  to HCI.
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.
1043 **
1044 *******************************************************************************/
1045 tBTM_STATUS  BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
1046                                        , tBT_TRANSPORT transport)
1047 {
1048     tBTM_INQ_INFO   *p_cur = NULL;
1049     tINQ_DB_ENT     *p_i;
1050
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]);
1054
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;
1058     }
1059     BTM_TRACE_API ("no device found in inquiry db\n");
1060
1061 #if (BLE_INCLUDED == TRUE)
1062     if (transport == BT_TRANSPORT_LE) {
1063         return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
1064     } else
1065 #endif
1066
1067         return (btm_initiate_rem_name (remote_bda, p_cur, BTM_RMT_NAME_EXT,
1068                                        BTM_EXT_RMT_NAME_TIMEOUT, p_cb));
1069 }
1070
1071 /*******************************************************************************
1072 **
1073 ** Function         BTM_CancelRemoteDeviceName
1074 **
1075 ** Description      This function initiates the cancel request for the specified
1076 **                  remote device.
1077 **
1078 ** Input Params:    None
1079 **
1080 ** Returns
1081 **                  BTM_CMD_STARTED is returned if the request was successfully sent
1082 **                                  to HCI.
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.
1085 **
1086 *******************************************************************************/
1087 tBTM_STATUS  BTM_CancelRemoteDeviceName (void)
1088 {
1089     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1090
1091     BTM_TRACE_API ("BTM_CancelRemoteDeviceName()\n");
1092
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);
1099             } else {
1100                 return (BTM_UNKNOWN_ADDR);
1101             }
1102         } else
1103 #endif
1104             if (btsnd_hcic_rmt_name_req_cancel (p_inq->remname_bda)) {
1105                 return (BTM_CMD_STARTED);
1106             } else {
1107                 return (BTM_NO_RESOURCES);
1108             }
1109     } else {
1110         return (BTM_WRONG_MODE);
1111     }
1112 }
1113
1114 /*******************************************************************************
1115 **
1116 ** Function         BTM_InqDbRead
1117 **
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.
1121 **
1122 ** Returns          pointer to entry, or NULL if not found
1123 **
1124 *******************************************************************************/
1125 tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
1126 {
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]);
1129
1130     tINQ_DB_ENT *p_ent = btm_inq_db_find(p_bda);
1131     if (!p_ent) {
1132         return NULL;
1133     }
1134
1135     return &p_ent->inq_info;
1136 }
1137
1138
1139 /*******************************************************************************
1140 **
1141 ** Function         BTM_InqDbFirst
1142 **
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.
1147 **
1148 ** Returns          pointer to first in-use entry, or NULL if DB is empty
1149 **
1150 *******************************************************************************/
1151 tBTM_INQ_INFO *BTM_InqDbFirst (void)
1152 {
1153     UINT16       xx;
1154     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1155
1156     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1157         if (p_ent->in_use) {
1158             return (&p_ent->inq_info);
1159         }
1160     }
1161
1162     /* If here, no used entry found */
1163     return ((tBTM_INQ_INFO *)NULL);
1164 }
1165
1166
1167 /*******************************************************************************
1168 **
1169 ** Function         BTM_InqDbNext
1170 **
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.
1174 **
1175 ** Returns          pointer to next in-use entry, or NULL if no more found.
1176 **
1177 *******************************************************************************/
1178 tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur)
1179 {
1180     tINQ_DB_ENT  *p_ent;
1181     UINT16        inx;
1182
1183     if (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);
1186
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);
1190             }
1191         }
1192
1193         /* If here, more entries found */
1194         return ((tBTM_INQ_INFO *)NULL);
1195     } else {
1196         return (BTM_InqDbFirst());
1197     }
1198 }
1199
1200
1201 /*******************************************************************************
1202 **
1203 ** Function         BTM_ClearInqDb
1204 **
1205 ** Description      This function is called to clear out a device or all devices
1206 **                  from the inquiry database.
1207 **
1208 ** Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1209 **                                              (NULL clears all entries)
1210 **
1211 ** Returns          BTM_BUSY if an inquiry, get remote name, or event filter
1212 **                          is active, otherwise BTM_SUCCESS
1213 **
1214 *******************************************************************************/
1215 tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda)
1216 {
1217     tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1218
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) {
1222         return (BTM_BUSY);
1223     }
1224
1225     btm_clr_inq_db(p_bda);
1226
1227     return (BTM_SUCCESS);
1228 }
1229
1230 /*******************************************************************************
1231 **
1232 ** Function         BTM_ReadInquiryRspTxPower
1233 **
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.
1237 **
1238 ** Returns          BTM_SUCCESS if successful
1239 **
1240 *******************************************************************************/
1241 tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb)
1242 {
1243     if (btm_cb.devcb.p_txpwer_cmpl_cb) {
1244         return (BTM_BUSY);
1245     }
1246
1247     btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT );
1248
1249
1250     btm_cb.devcb.p_txpwer_cmpl_cb = p_cb;
1251
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);
1256     } else {
1257         return (BTM_CMD_STARTED);
1258     }
1259 }
1260
1261 /*********************************************************************************
1262 **********************************************************************************
1263 **                                                                              **
1264 **                      BTM Internal Inquiry Functions                          **
1265 **                                                                              **
1266 **********************************************************************************
1267 *********************************************************************************/
1268 /*******************************************************************************
1269 **
1270 ** Function         btm_inq_db_reset
1271 **
1272 ** Description      This function is called at at reset to clear the inquiry
1273 **                  database & pending callback.
1274 **
1275 ** Returns          void
1276 **
1277 *******************************************************************************/
1278 void btm_inq_db_reset (void)
1279 {
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;
1284     tBTM_STATUS              status;
1285
1286     btu_stop_timer (&p_inq->inq_timer_ent);
1287
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;
1293
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) {
1298                 num_responses = 0;
1299                 (*p_inq->p_inq_cmpl_cb)(&num_responses);
1300             }
1301         }
1302     }
1303
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);
1309
1310         if (p_inq->p_remname_cmpl_cb) {
1311             rem_name.status = BTM_DEV_RESET;
1312
1313             (*p_inq->p_remname_cmpl_cb)(&rem_name);
1314             p_inq->p_remname_cmpl_cb = NULL;
1315         }
1316     }
1317
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;
1321
1322         if (p_inq->p_inqfilter_cmpl_cb) {
1323             status = BTM_DEV_RESET;
1324             (*p_inq->p_inqfilter_cmpl_cb)(&status);
1325         }
1326     }
1327
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();
1333
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;
1338
1339 #if BLE_INCLUDED == TRUE
1340     p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1341     p_inq->connectable_mode  |= BTM_BLE_NON_CONNECTABLE;
1342 #endif
1343     return;
1344 }
1345
1346
1347 /*********************************************************************************
1348 **
1349 ** Function         btm_inq_db_init
1350 **
1351 ** Description      This function is called at startup to initialize the inquiry
1352 **                  database.
1353 **
1354 ** Returns          void
1355 **
1356 *******************************************************************************/
1357 void btm_inq_db_init (void)
1358 {
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));
1361 #endif
1362
1363     btu_free_timer(&btm_cb.btm_inq_vars.rmt_name_timer_ent);
1364     memset(&btm_cb.btm_inq_vars.rmt_name_timer_ent, 0, sizeof(TIMER_LIST_ENT));
1365     btu_free_timer(&btm_cb.btm_inq_vars.inq_timer_ent);
1366     memset(&btm_cb.btm_inq_vars.inq_timer_ent, 0, sizeof(TIMER_LIST_ENT));
1367
1368     btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1369 }
1370
1371 /*********************************************************************************
1372 **
1373 ** Function         btm_inq_stop_on_ssp
1374 **
1375 ** Description      This function is called on incoming SSP
1376 **
1377 ** Returns          void
1378 **
1379 *******************************************************************************/
1380 void btm_inq_stop_on_ssp(void)
1381 {
1382     UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1383
1384 #if (BTM_INQ_DEBUG == TRUE)
1385     BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d\n",
1386                      btm_cb.btm_inq_vars.no_inc_ssp, btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1387 #endif
1388     if (btm_cb.btm_inq_vars.no_inc_ssp) {
1389         if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1390             if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1391                 BTM_CancelPeriodicInquiry();
1392             } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1393                 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1394                 btsnd_hcic_inq_cancel();
1395             }
1396         }
1397         /* do not allow inquiry to start */
1398         btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1399     }
1400 }
1401
1402 /*********************************************************************************
1403 **
1404 ** Function         btm_inq_clear_ssp
1405 **
1406 ** Description      This function is called when pairing_state becomes idle
1407 **
1408 ** Returns          void
1409 **
1410 *******************************************************************************/
1411 void btm_inq_clear_ssp(void)
1412 {
1413     btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1414 }
1415
1416 /*********************************************************************************
1417 **
1418 ** Function         btm_clr_inq_db
1419 **
1420 ** Description      This function is called to clear out a device or all devices
1421 **                  from the inquiry database.
1422 **
1423 ** Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1424 **                                              (NULL clears all entries)
1425 **
1426 ** Returns          void
1427 **
1428 *******************************************************************************/
1429 void btm_clr_inq_db (BD_ADDR p_bda)
1430 {
1431     tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1432     tINQ_DB_ENT             *p_ent = p_inq->inq_db;
1433     UINT16                   xx;
1434
1435 #if (BTM_INQ_DEBUG == TRUE)
1436     BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d\n",
1437                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1438 #endif
1439     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1440         if (p_ent->in_use) {
1441             /* If this is the specified BD_ADDR or clearing all devices */
1442             if (p_bda == NULL ||
1443                     (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1444                 p_ent->in_use = FALSE;
1445             }
1446         }
1447     }
1448 #if (BTM_INQ_DEBUG == TRUE)
1449     BTM_TRACE_DEBUG ("inq_active:0x%x state:%d\n",
1450                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1451 #endif
1452 }
1453
1454
1455 /*******************************************************************************
1456 **
1457 ** Function         btm_clr_inq_result_flt
1458 **
1459 ** Description      This function looks through the bdaddr database for a match
1460 **                  based on Bluetooth Device Address
1461 **
1462 ** Returns          TRUE if found, else FALSE (new entry)
1463 **
1464 *******************************************************************************/
1465 static void btm_clr_inq_result_flt (void)
1466 {
1467     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1468
1469     if (p_inq->p_bd_db) {
1470         osi_free(p_inq->p_bd_db);
1471         p_inq->p_bd_db = NULL;
1472     }
1473     p_inq->num_bd_entries = 0;
1474     p_inq->max_bd_entries = 0;
1475 }
1476
1477 /*******************************************************************************
1478 **
1479 ** Function         btm_inq_find_bdaddr
1480 **
1481 ** Description      This function looks through the bdaddr database for a match
1482 **                  based on Bluetooth Device Address
1483 **
1484 ** Returns          TRUE if found, else FALSE (new entry)
1485 **
1486 *******************************************************************************/
1487 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1488 {
1489     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1490     tINQ_BDADDR         *p_db = &p_inq->p_bd_db[0];
1491     UINT16       xx;
1492
1493     /* Don't bother searching, database doesn't exist or periodic mode */
1494     if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db) {
1495         return (FALSE);
1496     }
1497
1498     for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1499         if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1500                 && p_db->inq_count == p_inq->inq_counter) {
1501             return (TRUE);
1502         }
1503     }
1504
1505     if (xx < p_inq->max_bd_entries) {
1506         p_db->inq_count = p_inq->inq_counter;
1507         memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1508         p_inq->num_bd_entries++;
1509     }
1510
1511     /* If here, New Entry */
1512     return (FALSE);
1513 }
1514
1515 /*******************************************************************************
1516 **
1517 ** Function         btm_inq_db_find
1518 **
1519 ** Description      This function looks through the inquiry database for a match
1520 **                  based on Bluetooth Device Address
1521 **
1522 ** Returns          pointer to entry, or NULL if not found
1523 **
1524 *******************************************************************************/
1525 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1526 {
1527     UINT16       xx;
1528     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1529
1530     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1531         if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1532             return (p_ent);
1533         }
1534     }
1535
1536     /* If here, not found */
1537     return (NULL);
1538 }
1539
1540
1541 /*******************************************************************************
1542 **
1543 ** Function         btm_inq_db_new
1544 **
1545 ** Description      This function looks through the inquiry database for an unused
1546 **                  entry. If no entry is free, it allocates the oldest entry.
1547 **
1548 ** Returns          pointer to entry
1549 **
1550 *******************************************************************************/
1551 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1552 {
1553     UINT16       xx;
1554     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1555     tINQ_DB_ENT  *p_old = btm_cb.btm_inq_vars.inq_db;
1556     UINT32       ot = 0xFFFFFFFF;
1557
1558     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1559         if (!p_ent->in_use) {
1560             memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1561             memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1562             p_ent->in_use = TRUE;
1563
1564             return (p_ent);
1565         }
1566
1567         if (p_ent->time_of_resp < ot) {
1568             p_old = p_ent;
1569             ot    = p_ent->time_of_resp;
1570         }
1571     }
1572
1573     /* If here, no free entry found. Return the oldest. */
1574
1575     memset (p_old, 0, sizeof (tINQ_DB_ENT));
1576     memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1577     p_old->in_use = TRUE;
1578
1579     return (p_old);
1580 }
1581
1582
1583 /*******************************************************************************
1584 **
1585 ** Function         btm_set_inq_event_filter
1586 **
1587 ** Description      This function is called to set the inquiry event filter.
1588 **                  It is called by either internally, or by the external API function
1589 **                  (BTM_SetInqEventFilter).  It is used internally as part of the
1590 **                  inquiry processing.
1591 **
1592 ** Input Params:
1593 **                  filter_cond_type - this is the type of inquiry filter to apply:
1594 **                          BTM_FILTER_COND_DEVICE_CLASS,
1595 **                          BTM_FILTER_COND_BD_ADDR, or
1596 **                          BTM_CLR_INQUIRY_FILTER
1597 **
1598 **                  p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1599 **                          filter_cond_type  (See section 4.7.3 of Core Spec 1.0b).
1600 **
1601 ** Returns          BTM_CMD_STARTED if successfully initiated
1602 **                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
1603 **                  BTM_ILLEGAL_VALUE if a bad parameter was detected
1604 **
1605 *******************************************************************************/
1606 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1607         tBTM_INQ_FILT_COND *p_filt_cond)
1608 {
1609     UINT8    condition_length = DEV_CLASS_LEN * 2;
1610     UINT8    condition_buf[DEV_CLASS_LEN * 2];
1611     UINT8   *p_cond = condition_buf;                    /* points to the condition to pass to HCI */
1612
1613 #if (BTM_INQ_DEBUG == TRUE)
1614     BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]\n",
1615                      filter_cond_type);
1616     BTM_TRACE_DEBUG ("                       condition [%02x%02x%02x %02x%02x%02x]\n",
1617                      p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1618                      p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1619 #endif
1620
1621     /* Load the correct filter condition to pass to the lower layer */
1622     switch (filter_cond_type) {
1623     case BTM_FILTER_COND_DEVICE_CLASS:
1624         /* copy the device class and device class fields into contiguous memory to send to HCI */
1625         memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1626         memcpy (&condition_buf[DEV_CLASS_LEN],
1627                 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1628
1629         /* condition length should already be set as the default */
1630         break;
1631
1632     case BTM_FILTER_COND_BD_ADDR:
1633         p_cond = p_filt_cond->bdaddr_cond;
1634
1635         /* condition length should already be set as the default */
1636         break;
1637
1638     case BTM_CLR_INQUIRY_FILTER:
1639         condition_length = 0;
1640         break;
1641
1642     default:
1643         return (BTM_ILLEGAL_VALUE);     /* Bad parameter was passed in */
1644     }
1645
1646     btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1647
1648     /* Filter the inquiry results for the specified condition type and value */
1649     if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1650                                     p_cond, condition_length))
1651
1652     {
1653         return (BTM_CMD_STARTED);
1654     } else {
1655         return (BTM_NO_RESOURCES);
1656     }
1657 }
1658
1659
1660 /*******************************************************************************
1661 **
1662 ** Function         btm_event_filter_complete
1663 **
1664 ** Description      This function is called when a set event filter has completed.
1665 **                  Note: This routine currently only handles inquiry filters.
1666 **                      Connection filters are ignored for now.
1667 **
1668 ** Returns          void
1669 **
1670 *******************************************************************************/
1671 void btm_event_filter_complete (UINT8 *p)
1672 {
1673     UINT8            hci_status;
1674     tBTM_STATUS      status;
1675     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1676     tBTM_CMPL_CB   *p_cb = p_inq->p_inqfilter_cmpl_cb;
1677
1678 #if (BTM_INQ_DEBUG == TRUE)
1679     BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d\n",
1680                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1681 #endif
1682     /* If the filter complete event is from an old or cancelled request, ignore it */
1683     if (p_inq->pending_filt_complete_event) {
1684         p_inq->pending_filt_complete_event--;
1685         return;
1686     }
1687
1688     /* Only process the inquiry filter; Ignore the connection filter until it
1689        is used by the upper layers */
1690     if (p_inq->inqfilt_active == TRUE ) {
1691         /* Extract the returned status from the buffer */
1692         STREAM_TO_UINT8 (hci_status, p);
1693         if (hci_status != HCI_SUCCESS) {
1694             /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1695             BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)\n", hci_status);
1696             status = BTM_ERR_PROCESSING;
1697         } else {
1698             status = BTM_SUCCESS;
1699         }
1700
1701         /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1702            callback function to notify the initiator that it has completed */
1703         if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1704             p_inq->inqfilt_active = FALSE;
1705             if (p_cb) {
1706                 (*p_cb) (&status);
1707             }
1708         } else    /* An inquiry is active (the set filter command was internally generated),
1709                    process the next state of the process (Set a new filter or start the inquiry). */
1710         {
1711             if (status != BTM_SUCCESS) {
1712                 /* Process the inquiry complete (Error Status) */
1713                 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1714
1715                 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1716                 p_inq->inqfilt_active = FALSE;
1717                 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1718                 p_inq->state = BTM_INQ_INACTIVE_STATE;
1719
1720                 return;
1721             }
1722
1723             /* Check to see if a new filter needs to be set up */
1724             if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1725                 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED) {
1726                     p_inq->state = BTM_INQ_SET_FILT_STATE;
1727                 } else { /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1728                     p_inq->inqfilt_active = FALSE;
1729
1730                     /* Process the inquiry complete (Error Status) */
1731                     btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1732                 }
1733             } else { /* Initiate the Inquiry or Periodic Inquiry */
1734                 p_inq->state = BTM_INQ_ACTIVE_STATE;
1735                 p_inq->inqfilt_active = FALSE;
1736                 btm_initiate_inquiry (p_inq);
1737             }
1738         }
1739     }
1740 }
1741
1742
1743 /*******************************************************************************
1744 **
1745 ** Function         btm_initiate_inquiry
1746 **
1747 ** Description      This function is called to start an inquiry or periodic inquiry
1748 **                  upon completion of the setting and/or clearing of the inquiry filter.
1749 **
1750 ** Inputs:          p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1751 **                      mode - GENERAL or LIMITED inquiry
1752 **                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1753 **                      max_resps - maximum amount of devices to search for before ending the inquiry
1754 **                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1755 **                                         BTM_FILTER_COND_BD_ADDR
1756 **                      filter_cond - value for the filter (based on filter_cond_type)
1757 **
1758 ** Returns          If an error occurs the initiator's callback is called with the error status.
1759 **
1760 *******************************************************************************/
1761 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1762 {
1763     const LAP       *lap;
1764     tBTM_INQ_PARMS  *p_inqparms = &p_inq->inqparms;
1765
1766 #if (BTM_INQ_DEBUG == TRUE)
1767     BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d\n",
1768                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1769 #endif
1770     btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1771
1772     if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1773         btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1774         return;
1775     }
1776
1777     /* Make sure the number of responses doesn't overflow the database configuration */
1778     p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1779
1780     lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1781
1782     if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1783         if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1784                                       p_inq->per_min_delay,
1785                                       *lap, p_inqparms->duration,
1786                                       p_inqparms->max_resps)) {
1787             btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1788         }
1789     } else {
1790         btm_clr_inq_result_flt();
1791
1792         /* Allocate memory to hold bd_addrs responding */
1793         if ((p_inq->p_bd_db = (tINQ_BDADDR *)osi_calloc(BT_DEFAULT_BUFFER_SIZE)) != NULL) {
1794             p_inq->max_bd_entries = (UINT16)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1795             /*            BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1796                                           p_inq->max_bd_entries); */
1797         }
1798
1799         if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0)) {
1800             btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1801         }
1802     }
1803 }
1804
1805 /*******************************************************************************
1806 **
1807 ** Function         btm_process_inq_results
1808 **
1809 ** Description      This function is called when inquiry results are received from
1810 **                  the device. It updates the inquiry database. If the inquiry
1811 **                  database is full, the oldest entry is discarded.
1812 **
1813 ** Parameters       inq_res_mode - BTM_INQ_RESULT_STANDARD
1814 **                                 BTM_INQ_RESULT_WITH_RSSI
1815 **                                 BTM_INQ_RESULT_EXTENDED
1816 **
1817 ** Returns          void
1818 **
1819 *******************************************************************************/
1820 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1821 {
1822     UINT8            num_resp, xx;
1823     BD_ADDR          bda;
1824     tINQ_DB_ENT     *p_i;
1825     tBTM_INQ_RESULTS *p_cur = NULL;
1826     BOOLEAN          is_new = TRUE;
1827     BOOLEAN          update = FALSE;
1828     INT8             i_rssi;
1829     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1830     tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1831     UINT8            page_scan_rep_mode = 0;
1832     UINT8            page_scan_per_mode = 0;
1833     UINT8            page_scan_mode = 0;
1834     UINT8            rssi = 0;
1835     DEV_CLASS        dc;
1836     UINT16           clock_offset;
1837     UINT8            *p_eir_data = NULL;
1838
1839 #if (BTM_INQ_DEBUG == TRUE)
1840     BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d inq_res_mode=%d\n",
1841                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active, inq_res_mode);
1842 #endif
1843     /* Only process the results if the BR inquiry is still active */
1844     if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) {
1845         return;
1846     }
1847
1848     STREAM_TO_UINT8 (num_resp, p);
1849
1850     for (xx = 0; xx < num_resp; xx++) {
1851         update = FALSE;
1852         /* Extract inquiry results */
1853         STREAM_TO_BDADDR   (bda, p);
1854         STREAM_TO_UINT8    (page_scan_rep_mode, p);
1855         STREAM_TO_UINT8    (page_scan_per_mode, p);
1856
1857         if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1858             STREAM_TO_UINT8(page_scan_mode, p);
1859         }
1860
1861         STREAM_TO_DEVCLASS (dc, p);
1862         STREAM_TO_UINT16   (clock_offset, p);
1863         if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1864             STREAM_TO_UINT8(rssi, p);
1865         }
1866
1867         p_i = btm_inq_db_find (bda);
1868
1869         /* Only process the num_resp is smaller than max_resps.
1870            If results are queued to BTU task while canceling inquiry,
1871            or when more than one result is in this response, > max_resp
1872            responses could be processed which can confuse some apps
1873         */
1874         if (p_inq->inqparms.max_resps &&
1875                 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1876 #if BLE_INCLUDED == TRUE
1877                 /* new device response */
1878                 && ( p_i == NULL ||
1879                      /* exisiting device with BR/EDR info */
1880                      (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1881                    )
1882 #endif
1883
1884            ) {
1885             BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring\n");
1886             return;
1887         }
1888
1889         /* Check if this address has already been processed for this inquiry */
1890         if (btm_inq_find_bdaddr(bda)) {
1891             BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]\n",
1892                             bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
1893             /* By default suppose no update needed */
1894             i_rssi = (INT8)rssi;
1895
1896             /* If this new RSSI is higher than the last one */
1897             if (p_inq->inqparms.report_dup && (rssi != 0) &&
1898                     p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1899 #if BLE_INCLUDED == TRUE
1900                             /* BR/EDR inquiry information update */
1901                             || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1902 #endif
1903                            )) {
1904                 p_cur = &p_i->inq_info.results;
1905                 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d\n", i_rssi, p_cur->rssi);
1906                 p_cur->rssi = i_rssi;
1907                 update = TRUE;
1908             }
1909             /* If we received a second Extended Inq Event for an already */
1910             /* discovered device, this is because for the first one EIR was not received */
1911             else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1912                 p_cur = &p_i->inq_info.results;
1913                 update = TRUE;
1914             }
1915             /* If no update needed continue with next response (if any) */
1916             else {
1917                 continue;
1918             }
1919         }
1920
1921         /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
1922         if (p_i == NULL) {
1923             p_i = btm_inq_db_new (bda);
1924             is_new = TRUE;
1925         }
1926
1927         /* If an entry for the device already exists, overwrite it ONLY if it is from
1928            a previous inquiry. (Ignore it if it is a duplicate response from the same
1929            inquiry.
1930         */
1931         else if (p_i->inq_count == p_inq->inq_counter
1932 #if (BLE_INCLUDED == TRUE )
1933                  && (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)
1934 #endif
1935                 ) {
1936             is_new = FALSE;
1937         }
1938
1939         /* keep updating RSSI to have latest value */
1940         if ( inq_res_mode != BTM_INQ_RESULT_STANDARD ) {
1941             p_i->inq_info.results.rssi = (INT8)rssi;
1942         } else {
1943             p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1944         }
1945
1946         if (is_new == TRUE) {
1947             /* Save the info */
1948             p_cur = &p_i->inq_info.results;
1949             p_cur->page_scan_rep_mode = page_scan_rep_mode;
1950             p_cur->page_scan_per_mode = page_scan_per_mode;
1951             p_cur->page_scan_mode     = page_scan_mode;
1952             p_cur->dev_class[0]       = dc[0];
1953             p_cur->dev_class[1]       = dc[1];
1954             p_cur->dev_class[2]       = dc[2];
1955             p_cur->clock_offset       = clock_offset  | BTM_CLOCK_OFFSET_VALID;
1956
1957             p_i->time_of_resp = osi_time_get_os_boottime_ms();
1958
1959             if (p_i->inq_count != p_inq->inq_counter) {
1960                 p_inq->inq_cmpl_info.num_resp++;    /* A new response was found */
1961             }
1962
1963 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
1964             p_cur->inq_result_type    = BTM_INQ_RESULT_BR;
1965             if (p_i->inq_count != p_inq->inq_counter) {
1966                 p_cur->device_type  = BT_DEVICE_TYPE_BREDR;
1967                 p_i->scan_rsp       = FALSE;
1968             } else {
1969                 p_cur->device_type    |= BT_DEVICE_TYPE_BREDR;
1970             }
1971 #endif
1972             p_i->inq_count = p_inq->inq_counter;   /* Mark entry for current inquiry */
1973
1974             /* If the number of responses found and not unlimited, issue a cancel inquiry */
1975             if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1976                     p_inq->inqparms.max_resps &&
1977                     p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
1978 #if BLE_INCLUDED == TRUE
1979                     /* BLE scanning is active and received adv */
1980                     && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1981                          p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1982                         (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
1983 #endif
1984                ) {
1985                 /*                BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
1986                 btsnd_hcic_inq_cancel();
1987
1988 #if BLE_INCLUDED == TRUE
1989                 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) {
1990                     btm_ble_stop_inquiry();
1991                 }
1992 #endif
1993                 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
1994             }
1995             /* Initialize flag to FALSE. This flag is set/used by application */
1996             p_i->inq_info.appl_knows_rem_name = FALSE;
1997         }
1998
1999         if (is_new || update) {
2000             if ( inq_res_mode == BTM_INQ_RESULT_EXTENDED ) {
2001                 memset( p_cur->eir_uuid, 0,
2002                         BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
2003                 /* set bit map of UUID list from received EIR */
2004                 btm_set_eir_uuid( p, p_cur );
2005                 p_eir_data = p;
2006             } else {
2007                 p_eir_data = NULL;
2008             }
2009
2010             /* If a callback is registered, call it with the results */
2011             if (p_inq_results_cb) {
2012                 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2013             }
2014         }
2015     }
2016 }
2017
2018 /*******************************************************************************
2019 **
2020 ** Function         btm_sort_inq_result
2021 **
2022 ** Description      This function is called when inquiry complete is received
2023 **                  from the device to sort inquiry results based on rssi.
2024 **
2025 ** Returns          void
2026 **
2027 *******************************************************************************/
2028 void btm_sort_inq_result(void)
2029 {
2030     UINT8               xx, yy, num_resp;
2031     tINQ_DB_ENT         *p_tmp  = NULL;
2032     tINQ_DB_ENT         *p_ent  = btm_cb.btm_inq_vars.inq_db;
2033     tINQ_DB_ENT         *p_next = btm_cb.btm_inq_vars.inq_db + 1;
2034     int                 size;
2035
2036     num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE) ?
2037                btm_cb.btm_inq_vars.inq_cmpl_info.num_resp : BTM_INQ_DB_SIZE;
2038
2039     if ((p_tmp = (tINQ_DB_ENT *)osi_malloc(sizeof(tINQ_DB_ENT))) != NULL) {
2040         size = sizeof(tINQ_DB_ENT);
2041         for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
2042             for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
2043                 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
2044                     memcpy (p_tmp,  p_next, size);
2045                     memcpy (p_next, p_ent,  size);
2046                     memcpy (p_ent,  p_tmp,  size);
2047                 }
2048             }
2049         }
2050
2051         osi_free(p_tmp);
2052     }
2053 }
2054
2055 /*******************************************************************************
2056 **
2057 ** Function         btm_process_inq_complete
2058 **
2059 ** Description      This function is called when inquiry complete is received
2060 **                  from the device.  Call the callback if not in periodic inquiry
2061 **                  mode AND it is not NULL (The caller wants the event).
2062 **
2063 **                  The callback pass back the status and the number of responses
2064 **
2065 ** Returns          void
2066 **
2067 *******************************************************************************/
2068 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2069 {
2070     tBTM_CMPL_CB        *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2071     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2072
2073 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2074     /* inquiry inactive case happens when inquiry is cancelled.
2075        Make mode 0 for no further inquiries from the current inquiry process
2076     */
2077     if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH || !p_inq->inq_active) {
2078         /* re-initialize for next inquiry request */
2079         p_inq->next_state = BTM_BR_ONE;
2080         /* make the mode 0 here */
2081         p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2082
2083     }
2084 #endif
2085
2086 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2087     p_inq->inqparms.mode &= ~(mode);
2088 #endif
2089
2090     if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
2091         /*end of LE observe*/
2092         p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2093         p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2094         p_inq->scan_type = INQ_NONE;
2095     }
2096
2097
2098 #if (BTM_INQ_DEBUG == TRUE)
2099     BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d\n",
2100                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2101 #endif
2102     btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2103     /* Ignore any stray or late complete messages if the inquiry is not active */
2104     if (p_inq->inq_active) {
2105         p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2106
2107         /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2108         if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0) {
2109 #if BLE_INCLUDED == TRUE
2110             btm_clear_all_pending_le_entry();
2111 #endif
2112             p_inq->state = BTM_INQ_INACTIVE_STATE;
2113
2114             /* Increment so the start of a next inquiry has a new count */
2115             p_inq->inq_counter++;
2116
2117             btm_clr_inq_result_flt();
2118
2119             if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2120                     controller_get_interface()->supports_rssi_with_inquiry_results()) {
2121                 btm_sort_inq_result();
2122             }
2123
2124             /* Clear the results callback if set */
2125             p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2126             p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2127             p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2128
2129             /* If we have a callback registered for inquiry complete, call it */
2130             BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d\n",
2131                              p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2132
2133             if (p_inq_cb) {
2134                 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2135             }
2136         }
2137 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2138         if (p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
2139             /* make inquiry inactive for next iteration */
2140             p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2141             /* call the inquiry again */
2142             BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb, p_inq->p_inq_cmpl_cb);
2143         }
2144 #endif
2145     }
2146     if (p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL) { //this inquiry is complete
2147         p_inq->scan_type = INQ_NONE;
2148 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2149         /* check if the LE observe is pending */
2150         if (p_inq->p_inq_ble_results_cb != NULL) {
2151             BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2152             BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2153         }
2154 #endif
2155     }
2156 #if (BTM_INQ_DEBUG == TRUE)
2157     BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d\n",
2158                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2159 #endif
2160 }
2161
2162 /*******************************************************************************
2163 **
2164 ** Function         btm_process_cancel_complete
2165 **
2166 ** Description      This function is called when inquiry cancel complete is received
2167 **                  from the device.This function will also call the btm_process_inq_complete
2168 **                  This function is needed to differentiate a cancel_cmpl_evt from the
2169 **                  inq_cmpl_evt
2170 **
2171 ** Returns          void
2172 **
2173 *******************************************************************************/
2174 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2175 {
2176     btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2177     btm_process_inq_complete(status, mode);
2178 }
2179 /*******************************************************************************
2180 **
2181 ** Function         btm_initiate_rem_name
2182 **
2183 ** Description      This function looks initiates a remote name request.  It is called
2184 **                  either by GAP or by the API call BTM_ReadRemoteDeviceName.
2185 **
2186 ** Input Params:    p_cur         - pointer to an inquiry result structure (NULL if nonexistent)
2187 **                  p_cb            - callback function called when BTM_CMD_STARTED
2188 **                                    is returned.
2189 **                                    A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2190 **                                    callback.
2191 **
2192 ** Returns
2193 **                  BTM_CMD_STARTED is returned if the request was sent to HCI.
2194 **                  BTM_BUSY if already in progress
2195 **                  BTM_NO_RESOURCES if could not allocate resources to start the command
2196 **                  BTM_WRONG_MODE if the device is not up.
2197 **
2198 *******************************************************************************/
2199 tBTM_STATUS  btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2200                                     UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2201 {
2202     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2203     BOOLEAN              cmd_ok;
2204
2205
2206     /*** Make sure the device is ready ***/
2207     if (!BTM_IsDeviceUp()) {
2208         return (BTM_WRONG_MODE);
2209     }
2210
2211
2212     if (origin == BTM_RMT_NAME_SEC) {
2213         cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2214                                           HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2215         if (cmd_ok) {
2216             return BTM_CMD_STARTED;
2217         } else {
2218             return BTM_NO_RESOURCES;
2219         }
2220     }
2221     /* Make sure there are no two remote name requests from external API in progress */
2222     else if (origin == BTM_RMT_NAME_EXT) {
2223         if (p_inq->remname_active) {
2224             return (BTM_BUSY);
2225         } else {
2226             /* If there is no remote name request running,call the callback function and start timer */
2227             p_inq->p_remname_cmpl_cb = p_cb;
2228             memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2229             btu_start_timer (&p_inq->rmt_name_timer_ent,
2230                              BTU_TTYPE_BTM_RMT_NAME,
2231                              timeout);
2232
2233             /* If the database entry exists for the device, use its clock offset */
2234             if (p_cur) {
2235                 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2236                                                   p_cur->results.page_scan_rep_mode,
2237                                                   p_cur->results.page_scan_mode,
2238                                                   (UINT16)(p_cur->results.clock_offset |
2239                                                           BTM_CLOCK_OFFSET_VALID));
2240             } else { /* Otherwise use defaults and mark the clock offset as invalid */
2241                 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2242                                                   HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2243             }
2244             if (cmd_ok) {
2245                 p_inq->remname_active = TRUE;
2246                 return BTM_CMD_STARTED;
2247             } else {
2248                 return BTM_NO_RESOURCES;
2249             }
2250         }
2251     } else {
2252         return BTM_ILLEGAL_VALUE;
2253     }
2254 }
2255
2256 /*******************************************************************************
2257 **
2258 ** Function         btm_process_remote_name
2259 **
2260 ** Description      This function is called when a remote name is received from
2261 **                  the device. If remote names are cached, it updates the inquiry
2262 **                  database.
2263 **
2264 ** Returns          void
2265 **
2266 *******************************************************************************/
2267 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2268 {
2269     tBTM_REMOTE_DEV_NAME    rem_name;
2270     tBTM_INQUIRY_VAR_ST    *p_inq = &btm_cb.btm_inq_vars;
2271     tBTM_CMPL_CB           *p_cb = p_inq->p_remname_cmpl_cb;
2272     UINT8                  *p_n1;
2273
2274     UINT16                 temp_evt_len;
2275
2276     if (bda != NULL) {
2277         BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x\n", bda[0], bda[1],
2278                         bda[2], bda[3],
2279                         bda[4], bda[5]);
2280     }
2281
2282     BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x\n", p_inq->remname_bda[0], p_inq->remname_bda[1],
2283                     p_inq->remname_bda[2], p_inq->remname_bda[3],
2284                     p_inq->remname_bda[4], p_inq->remname_bda[5]);
2285
2286
2287
2288     /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2289     if ((p_inq->remname_active == TRUE) &&
2290             (((bda != NULL) &&
2291               (memcmp(bda, p_inq->remname_bda, BD_ADDR_LEN) == 0)) || bda == NULL))
2292
2293     {
2294 #if BLE_INCLUDED == TRUE
2295         if (BTM_UseLeLink(p_inq->remname_bda)) {
2296             if (hci_status == HCI_ERR_UNSPECIFIED) {
2297                 btm_ble_cancel_remote_name(p_inq->remname_bda);
2298             }
2299         }
2300 #endif
2301         btu_stop_timer (&p_inq->rmt_name_timer_ent);
2302         p_inq->remname_active = FALSE;
2303         /* Clean up and return the status if the command was not successful */
2304         /* Note: If part of the inquiry, the name is not stored, and the    */
2305         /*       inquiry complete callback is called.                       */
2306
2307         if (hci_status == HCI_SUCCESS) {
2308             /* Copy the name from the data stream into the return structure */
2309             /* Note that even if it is not being returned, it is used as a  */
2310             /*      temporary buffer.                                       */
2311             p_n1 = (UINT8 *)rem_name.remote_bd_name;
2312             rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2313             rem_name.remote_bd_name[rem_name.length] = 0;
2314             rem_name.status = BTM_SUCCESS;
2315             temp_evt_len = rem_name.length;
2316
2317             while (temp_evt_len > 0) {
2318                 *p_n1++ = *bdn++;
2319                 temp_evt_len--;
2320             }
2321             rem_name.remote_bd_name[rem_name.length] = 0;
2322         }
2323
2324
2325         /* If processing a stand alone remote name then report the error in the callback */
2326         else {
2327             rem_name.status = BTM_BAD_VALUE_RET;
2328             rem_name.length = 0;
2329             rem_name.remote_bd_name[0] = 0;
2330         }
2331         /* Reset the remote BAD to zero and call callback if possible */
2332         memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2333
2334         p_inq->p_remname_cmpl_cb = NULL;
2335         if (p_cb) {
2336             (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2337         }
2338     }
2339 }
2340
2341 /*******************************************************************************
2342 **
2343 ** Function         btm_inq_rmt_name_failed
2344 **
2345 ** Description      This function is if timeout expires while getting remote
2346 **                  name.  This is done for devices that incorrectly do not
2347 **                  report operation failure
2348 **
2349 ** Returns          void
2350 **
2351 *******************************************************************************/
2352 void btm_inq_rmt_name_failed (void)
2353 {
2354     BTM_TRACE_ERROR ("btm_inq_rmt_name_failed()  remname_active=%d\n", btm_cb.btm_inq_vars.remname_active);
2355
2356     if (btm_cb.btm_inq_vars.remname_active) {
2357         btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2358     } else {
2359         btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2360     }
2361 #if (SMP_INCLUDED == TRUE)
2362     btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2363 #endif  ///SMP_INCLUDED == TRUE
2364 }
2365 /*******************************************************************************
2366 **
2367 ** Function         btm_read_linq_tx_power_complete
2368 **
2369 ** Description      read inquiry tx power level complete callback function.
2370 **
2371 ** Returns          void
2372 **
2373 *******************************************************************************/
2374 void btm_read_linq_tx_power_complete(UINT8 *p)
2375 {
2376     tBTM_CMPL_CB                *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2377     tBTM_INQ_TXPWR_RESULTS        results;
2378
2379     btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2380     /* If there was a callback registered for read inq tx power, call it */
2381     btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2382
2383     if (p_cb) {
2384         STREAM_TO_UINT8  (results.hci_status, p);
2385
2386         if (results.hci_status == HCI_SUCCESS) {
2387             results.status = BTM_SUCCESS;
2388
2389             STREAM_TO_UINT8 (results.tx_power, p);
2390             BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n",
2391                              results.tx_power, results.hci_status);
2392         } else {
2393             results.status = BTM_ERR_PROCESSING;
2394         }
2395
2396         (*p_cb)(&results);
2397     }
2398
2399 }
2400 /*******************************************************************************
2401 **
2402 ** Function         BTM_WriteEIR
2403 **
2404 ** Description      This function is called to write EIR data to controller.
2405 **
2406 ** Parameters       p_buff - allocated HCI command buffer including extended
2407 **                           inquriry response
2408 **
2409 ** Returns          BTM_SUCCESS  - if successful
2410 **                  BTM_MODE_UNSUPPORTED - if local device cannot support it
2411 **
2412 *******************************************************************************/
2413 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2414 {
2415     if (controller_get_interface()->supports_extended_inquiry_response()) {
2416         BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
2417         btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2418         return BTM_SUCCESS;
2419     } else {
2420         osi_free(p_buff);
2421         return BTM_MODE_UNSUPPORTED;
2422     }
2423 }
2424
2425 /*******************************************************************************
2426 **
2427 ** Function         BTM_CheckEirData
2428 **
2429 ** Description      This function is called to get EIR data from significant part.
2430 **
2431 ** Parameters       p_eir - pointer of EIR significant part
2432 **                  type   - finding EIR data type
2433 **                  p_length - return the length of EIR data not including type
2434 **
2435 ** Returns          pointer of EIR data
2436 **
2437 *******************************************************************************/
2438 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2439 {
2440     UINT8 *p = p_eir;
2441     UINT8 length;
2442     UINT8 eir_type;
2443     BTM_TRACE_API("BTM_CheckEirData type=0x%02X\n", type);
2444
2445     STREAM_TO_UINT8(length, p);
2446     while ( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN)) {
2447         STREAM_TO_UINT8(eir_type, p);
2448         if ( eir_type == type ) {
2449             /* length doesn't include itself */
2450             *p_length = length - 1; /* minus the length of type */
2451             return p;
2452         }
2453         p += length - 1; /* skip the length of data */
2454         STREAM_TO_UINT8(length, p);
2455     }
2456
2457     *p_length = 0;
2458     return NULL;
2459 }
2460
2461 /*******************************************************************************
2462 **
2463 ** Function         btm_convert_uuid_to_eir_service
2464 **
2465 ** Description      This function is called to get the bit position of UUID.
2466 **
2467 ** Parameters       uuid16 - UUID 16-bit
2468 **
2469 ** Returns          BTM EIR service ID if found
2470 **                  BTM_EIR_MAX_SERVICES - if not found
2471 **
2472 *******************************************************************************/
2473 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2474 {
2475     UINT8 xx;
2476
2477     for ( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ ) {
2478         if ( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
2479             return xx;
2480         }
2481     }
2482     return BTM_EIR_MAX_SERVICES;
2483 }
2484
2485 /*******************************************************************************
2486 **
2487 ** Function         BTM_HasEirService
2488 **
2489 ** Description      This function is called to know if UUID in bit map of UUID.
2490 **
2491 ** Parameters       p_eir_uuid - bit map of UUID list
2492 **                  uuid16 - UUID 16-bit
2493 **
2494 ** Returns          TRUE - if found
2495 **                  FALSE - if not found
2496 **
2497 *******************************************************************************/
2498 BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2499 {
2500     UINT8 service_id;
2501
2502     service_id = btm_convert_uuid_to_eir_service(uuid16);
2503     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2504         return ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2505     } else {
2506         return ( FALSE );
2507     }
2508 }
2509
2510 /*******************************************************************************
2511 **
2512 ** Function         BTM_HasInquiryEirService
2513 **
2514 ** Description      This function is called to know if UUID in bit map of UUID list.
2515 **
2516 ** Parameters       p_results - inquiry results
2517 **                  uuid16 - UUID 16-bit
2518 **
2519 ** Returns          BTM_EIR_FOUND - if found
2520 **                  BTM_EIR_NOT_FOUND - if not found and it is complete list
2521 **                  BTM_EIR_UNKNOWN - if not found and it is not complete list
2522 **
2523 *******************************************************************************/
2524 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2525 {
2526     if ( BTM_HasEirService( p_results->eir_uuid, uuid16 )) {
2527         return BTM_EIR_FOUND;
2528     } else if ( p_results->eir_complete_list ) {
2529         return BTM_EIR_NOT_FOUND;
2530     } else {
2531         return BTM_EIR_UNKNOWN;
2532     }
2533 }
2534
2535 /*******************************************************************************
2536 **
2537 ** Function         BTM_AddEirService
2538 **
2539 ** Description      This function is called to add a service in bit map of UUID list.
2540 **
2541 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2542 **                  uuid16 - UUID 16-bit
2543 **
2544 ** Returns          None
2545 **
2546 *******************************************************************************/
2547 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2548 {
2549     UINT8 service_id;
2550
2551     service_id = btm_convert_uuid_to_eir_service(uuid16);
2552     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2553         BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2554     }
2555 }
2556
2557 /*******************************************************************************
2558 **
2559 ** Function         BTM_RemoveEirService
2560 **
2561 ** Description      This function is called to remove a service in bit map of UUID list.
2562 **
2563 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2564 **                  uuid16 - UUID 16-bit
2565 **
2566 ** Returns          None
2567 **
2568 *******************************************************************************/
2569 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2570 {
2571     UINT8 service_id;
2572
2573     service_id = btm_convert_uuid_to_eir_service(uuid16);
2574     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2575         BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2576     }
2577 }
2578
2579 /*******************************************************************************
2580 **
2581 ** Function         BTM_GetEirSupportedServices
2582 **
2583 ** Description      This function is called to get UUID list from bit map of UUID list.
2584 **
2585 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2586 **                  p - reference of current pointer of EIR
2587 **                  max_num_uuid16 - max number of UUID can be written in EIR
2588 **                  num_uuid16 - number of UUID have been written in EIR
2589 **
2590 ** Returns          BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2591 **                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2592 **
2593 *******************************************************************************/
2594 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid,    UINT8 **p,
2595                                    UINT8  max_num_uuid16, UINT8 *p_num_uuid16)
2596 {
2597     UINT8 service_index;
2598
2599     *p_num_uuid16 = 0;
2600
2601     for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++) {
2602         if ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index )) {
2603             if ( *p_num_uuid16 < max_num_uuid16 ) {
2604                 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2605                 (*p_num_uuid16)++;
2606             }
2607             /* if max number of UUIDs are stored and found one more */
2608             else {
2609                 return BTM_EIR_MORE_16BITS_UUID_TYPE;
2610             }
2611         }
2612     }
2613     return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2614 }
2615
2616 /*******************************************************************************
2617 **
2618 ** Function         BTM_GetEirUuidList
2619 **
2620 ** Description      This function parses EIR and returns UUID list.
2621 **
2622 ** Parameters       p_eir - EIR
2623 **                  uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2624 **                  p_num_uuid - return number of UUID in found list
2625 **                  p_uuid_list - return UUID list
2626 **                  max_num_uuid - maximum number of UUID to be returned
2627 **
2628 ** Returns          0 - if not found
2629 **                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2630 **                  BTM_EIR_MORE_16BITS_UUID_TYPE
2631 **                  BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2632 **                  BTM_EIR_MORE_32BITS_UUID_TYPE
2633 **                  BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2634 **                  BTM_EIR_MORE_128BITS_UUID_TYPE
2635 **
2636 *******************************************************************************/
2637 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2638                           UINT8 *p_uuid_list, UINT8 max_num_uuid)
2639 {
2640     UINT8   *p_uuid_data;
2641     UINT8   type;
2642     UINT8   yy, xx;
2643     UINT16  *p_uuid16 = (UINT16 *)p_uuid_list;
2644     UINT32  *p_uuid32 = (UINT32 *)p_uuid_list;
2645     char    buff[LEN_UUID_128 * 2 + 1];
2646
2647     p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2648     if ( p_uuid_data == NULL ) {
2649         return 0x00;
2650     }
2651
2652     if ( *p_num_uuid > max_num_uuid ) {
2653         BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d\n",
2654                           *p_num_uuid, max_num_uuid );
2655         *p_num_uuid = max_num_uuid;
2656     }
2657
2658     BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d\n", type, *p_num_uuid );
2659
2660     if ( uuid_size == LEN_UUID_16 ) {
2661         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2662             STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2663             BTM_TRACE_DEBUG("                     0x%04X\n", *(p_uuid16 + yy));
2664         }
2665     } else if ( uuid_size == LEN_UUID_32 ) {
2666         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2667             STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2668             BTM_TRACE_DEBUG("                     0x%08X\n", *(p_uuid32 + yy));
2669         }
2670     } else if ( uuid_size == LEN_UUID_128 ) {
2671         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2672             STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2673             for ( xx = 0; xx < LEN_UUID_128; xx++ ) {
2674                 sprintf(buff + xx * 2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2675             }
2676             BTM_TRACE_DEBUG("                     0x%s\n", buff);
2677         }
2678     }
2679
2680     return type;
2681 }
2682
2683
2684 /*******************************************************************************
2685 **
2686 ** Function         btm_eir_get_uuid_list
2687 **
2688 ** Description      This function searches UUID list in EIR.
2689 **
2690 ** Parameters       p_eir - address of EIR
2691 **                  uuid_size - size of UUID to find
2692 **                  p_num_uuid - number of UUIDs found
2693 **                  p_uuid_list_type - EIR data type
2694 **
2695 ** Returns          NULL - if UUID list with uuid_size is not found
2696 **                  beginning of UUID list in EIR - otherwise
2697 **
2698 *******************************************************************************/
2699 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2700                                      UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2701 {
2702     UINT8   *p_uuid_data;
2703     UINT8   complete_type, more_type;
2704     UINT8   uuid_len;
2705
2706     switch ( uuid_size ) {
2707     case LEN_UUID_16:
2708         complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2709         more_type     = BTM_EIR_MORE_16BITS_UUID_TYPE;
2710         break;
2711     case LEN_UUID_32:
2712         complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2713         more_type     = BTM_EIR_MORE_32BITS_UUID_TYPE;
2714         break;
2715     case LEN_UUID_128:
2716         complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2717         more_type     = BTM_EIR_MORE_128BITS_UUID_TYPE;
2718         break;
2719     default:
2720         *p_num_uuid = 0;
2721         return NULL;
2722         break;
2723     }
2724
2725     p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2726     if (p_uuid_data == NULL) {
2727         p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2728         *p_uuid_list_type = more_type;
2729     } else {
2730         *p_uuid_list_type = complete_type;
2731     }
2732
2733     *p_num_uuid = uuid_len / uuid_size;
2734     return p_uuid_data;
2735 }
2736
2737 /*******************************************************************************
2738 **
2739 ** Function         btm_convert_uuid_to_uuid16
2740 **
2741 ** Description      This function converts UUID to UUID 16-bit.
2742 **
2743 ** Parameters       p_uuid - address of UUID
2744 **                  uuid_size - size of UUID
2745 **
2746 ** Returns          0 - if UUID cannot be converted to UUID 16-bit
2747 **                  UUID 16-bit - otherwise
2748 **
2749 *******************************************************************************/
2750 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2751 {
2752     static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2753                                                    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2754                                                   };
2755     UINT16 uuid16 = 0;
2756     UINT32 uuid32;
2757     BOOLEAN is_base_uuid;
2758     UINT8  xx;
2759
2760     switch (uuid_size) {
2761     case LEN_UUID_16:
2762         STREAM_TO_UINT16 (uuid16, p_uuid);
2763         break;
2764     case LEN_UUID_32:
2765         STREAM_TO_UINT32 (uuid32, p_uuid);
2766         if (uuid32 < 0x10000) {
2767             uuid16 = (UINT16) uuid32;
2768         }
2769         break;
2770     case LEN_UUID_128:
2771         /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2772         is_base_uuid = TRUE;
2773         for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
2774             if (p_uuid[xx] != base_uuid[xx]) {
2775                 is_base_uuid = FALSE;
2776                 break;
2777             }
2778         }
2779         if (is_base_uuid) {
2780             if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0)) {
2781                 p_uuid += (LEN_UUID_128 - 4);
2782                 STREAM_TO_UINT16(uuid16, p_uuid);
2783             }
2784         }
2785         break;
2786     default:
2787         BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size\n");
2788         break;
2789     }
2790
2791     return ( uuid16);
2792 }
2793
2794 /*******************************************************************************
2795 **
2796 ** Function         btm_set_eir_uuid
2797 **
2798 ** Description      This function is called to store received UUID into inquiry result.
2799 **
2800 ** Parameters       p_eir - pointer of EIR significant part
2801 **                  p_results - pointer of inquiry result
2802 **
2803 ** Returns          None
2804 **
2805 *******************************************************************************/
2806 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2807 {
2808     UINT8   *p_uuid_data;
2809     UINT8   num_uuid;
2810     UINT16  uuid16;
2811     UINT8   yy;
2812     UINT8   type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2813
2814     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2815
2816     if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
2817         p_results->eir_complete_list = TRUE;
2818     } else {
2819         p_results->eir_complete_list = FALSE;
2820     }
2821
2822     BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X\n", p_results->eir_complete_list);
2823
2824     if ( p_uuid_data ) {
2825         for ( yy = 0; yy < num_uuid; yy++ ) {
2826             STREAM_TO_UINT16(uuid16, p_uuid_data);
2827             BTM_AddEirService( p_results->eir_uuid, uuid16 );
2828         }
2829     }
2830
2831     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2832     if ( p_uuid_data ) {
2833         for ( yy = 0; yy < num_uuid; yy++ ) {
2834             uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2835             p_uuid_data += LEN_UUID_32;
2836             if ( uuid16 ) {
2837                 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2838             }
2839         }
2840     }
2841
2842     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2843     if ( p_uuid_data ) {
2844         for ( yy = 0; yy < num_uuid; yy++ ) {
2845             uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2846             p_uuid_data += LEN_UUID_128;
2847             if ( uuid16 ) {
2848                 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2849             }
2850         }
2851     }
2852 }