]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/stack/btm/btm_inq.c
d9baa4b81c5490a2827cf0afd38d4f066c2e6198
[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 "alarm.h"
33 #include "bt_types.h"
34 #include "controller.h"
35 #include "hcimsgs.h"
36 #include "btu.h"
37 #include "btm_api.h"
38 #include "btm_int.h"
39 #include "hcidefs.h"
40 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
41 #include "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     btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1363 }
1364
1365 /*********************************************************************************
1366 **
1367 ** Function         btm_inq_stop_on_ssp
1368 **
1369 ** Description      This function is called on incoming SSP
1370 **
1371 ** Returns          void
1372 **
1373 *******************************************************************************/
1374 void btm_inq_stop_on_ssp(void)
1375 {
1376     UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE | BTM_LIMITED_INQUIRY_ACTIVE);
1377
1378 #if (BTM_INQ_DEBUG == TRUE)
1379     BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d\n",
1380                      btm_cb.btm_inq_vars.no_inc_ssp, btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1381 #endif
1382     if (btm_cb.btm_inq_vars.no_inc_ssp) {
1383         if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE) {
1384             if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1385                 BTM_CancelPeriodicInquiry();
1386             } else if (btm_cb.btm_inq_vars.inq_active & normal_active) {
1387                 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1388                 btsnd_hcic_inq_cancel();
1389             }
1390         }
1391         /* do not allow inquiry to start */
1392         btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1393     }
1394 }
1395
1396 /*********************************************************************************
1397 **
1398 ** Function         btm_inq_clear_ssp
1399 **
1400 ** Description      This function is called when pairing_state becomes idle
1401 **
1402 ** Returns          void
1403 **
1404 *******************************************************************************/
1405 void btm_inq_clear_ssp(void)
1406 {
1407     btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1408 }
1409
1410 /*********************************************************************************
1411 **
1412 ** Function         btm_clr_inq_db
1413 **
1414 ** Description      This function is called to clear out a device or all devices
1415 **                  from the inquiry database.
1416 **
1417 ** Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1418 **                                              (NULL clears all entries)
1419 **
1420 ** Returns          void
1421 **
1422 *******************************************************************************/
1423 void btm_clr_inq_db (BD_ADDR p_bda)
1424 {
1425     tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1426     tINQ_DB_ENT             *p_ent = p_inq->inq_db;
1427     UINT16                   xx;
1428
1429 #if (BTM_INQ_DEBUG == TRUE)
1430     BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d\n",
1431                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1432 #endif
1433     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1434         if (p_ent->in_use) {
1435             /* If this is the specified BD_ADDR or clearing all devices */
1436             if (p_bda == NULL ||
1437                     (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1438                 p_ent->in_use = FALSE;
1439             }
1440         }
1441     }
1442 #if (BTM_INQ_DEBUG == TRUE)
1443     BTM_TRACE_DEBUG ("inq_active:0x%x state:%d\n",
1444                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1445 #endif
1446 }
1447
1448
1449 /*******************************************************************************
1450 **
1451 ** Function         btm_clr_inq_result_flt
1452 **
1453 ** Description      This function looks through the bdaddr database for a match
1454 **                  based on Bluetooth Device Address
1455 **
1456 ** Returns          TRUE if found, else FALSE (new entry)
1457 **
1458 *******************************************************************************/
1459 static void btm_clr_inq_result_flt (void)
1460 {
1461     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1462
1463     if (p_inq->p_bd_db) {
1464         osi_free(p_inq->p_bd_db);
1465         p_inq->p_bd_db = NULL;
1466     }
1467     p_inq->num_bd_entries = 0;
1468     p_inq->max_bd_entries = 0;
1469 }
1470
1471 /*******************************************************************************
1472 **
1473 ** Function         btm_inq_find_bdaddr
1474 **
1475 ** Description      This function looks through the bdaddr database for a match
1476 **                  based on Bluetooth Device Address
1477 **
1478 ** Returns          TRUE if found, else FALSE (new entry)
1479 **
1480 *******************************************************************************/
1481 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1482 {
1483     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1484     tINQ_BDADDR         *p_db = &p_inq->p_bd_db[0];
1485     UINT16       xx;
1486
1487     /* Don't bother searching, database doesn't exist or periodic mode */
1488     if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db) {
1489         return (FALSE);
1490     }
1491
1492     for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++) {
1493         if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1494                 && p_db->inq_count == p_inq->inq_counter) {
1495             return (TRUE);
1496         }
1497     }
1498
1499     if (xx < p_inq->max_bd_entries) {
1500         p_db->inq_count = p_inq->inq_counter;
1501         memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1502         p_inq->num_bd_entries++;
1503     }
1504
1505     /* If here, New Entry */
1506     return (FALSE);
1507 }
1508
1509 /*******************************************************************************
1510 **
1511 ** Function         btm_inq_db_find
1512 **
1513 ** Description      This function looks through the inquiry database for a match
1514 **                  based on Bluetooth Device Address
1515 **
1516 ** Returns          pointer to entry, or NULL if not found
1517 **
1518 *******************************************************************************/
1519 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1520 {
1521     UINT16       xx;
1522     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1523
1524     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1525         if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN))) {
1526             return (p_ent);
1527         }
1528     }
1529
1530     /* If here, not found */
1531     return (NULL);
1532 }
1533
1534
1535 /*******************************************************************************
1536 **
1537 ** Function         btm_inq_db_new
1538 **
1539 ** Description      This function looks through the inquiry database for an unused
1540 **                  entry. If no entry is free, it allocates the oldest entry.
1541 **
1542 ** Returns          pointer to entry
1543 **
1544 *******************************************************************************/
1545 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1546 {
1547     UINT16       xx;
1548     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1549     tINQ_DB_ENT  *p_old = btm_cb.btm_inq_vars.inq_db;
1550     UINT32       ot = 0xFFFFFFFF;
1551
1552     for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
1553         if (!p_ent->in_use) {
1554             memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1555             memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1556             p_ent->in_use = TRUE;
1557
1558             return (p_ent);
1559         }
1560
1561         if (p_ent->time_of_resp < ot) {
1562             p_old = p_ent;
1563             ot    = p_ent->time_of_resp;
1564         }
1565     }
1566
1567     /* If here, no free entry found. Return the oldest. */
1568
1569     memset (p_old, 0, sizeof (tINQ_DB_ENT));
1570     memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1571     p_old->in_use = TRUE;
1572
1573     return (p_old);
1574 }
1575
1576
1577 /*******************************************************************************
1578 **
1579 ** Function         btm_set_inq_event_filter
1580 **
1581 ** Description      This function is called to set the inquiry event filter.
1582 **                  It is called by either internally, or by the external API function
1583 **                  (BTM_SetInqEventFilter).  It is used internally as part of the
1584 **                  inquiry processing.
1585 **
1586 ** Input Params:
1587 **                  filter_cond_type - this is the type of inquiry filter to apply:
1588 **                          BTM_FILTER_COND_DEVICE_CLASS,
1589 **                          BTM_FILTER_COND_BD_ADDR, or
1590 **                          BTM_CLR_INQUIRY_FILTER
1591 **
1592 **                  p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1593 **                          filter_cond_type  (See section 4.7.3 of Core Spec 1.0b).
1594 **
1595 ** Returns          BTM_CMD_STARTED if successfully initiated
1596 **                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
1597 **                  BTM_ILLEGAL_VALUE if a bad parameter was detected
1598 **
1599 *******************************************************************************/
1600 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1601         tBTM_INQ_FILT_COND *p_filt_cond)
1602 {
1603     UINT8    condition_length = DEV_CLASS_LEN * 2;
1604     UINT8    condition_buf[DEV_CLASS_LEN * 2];
1605     UINT8   *p_cond = condition_buf;                    /* points to the condition to pass to HCI */
1606
1607 #if (BTM_INQ_DEBUG == TRUE)
1608     BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]\n",
1609                      filter_cond_type);
1610     BTM_TRACE_DEBUG ("                       condition [%02x%02x%02x %02x%02x%02x]\n",
1611                      p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1612                      p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1613 #endif
1614
1615     /* Load the correct filter condition to pass to the lower layer */
1616     switch (filter_cond_type) {
1617     case BTM_FILTER_COND_DEVICE_CLASS:
1618         /* copy the device class and device class fields into contiguous memory to send to HCI */
1619         memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1620         memcpy (&condition_buf[DEV_CLASS_LEN],
1621                 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1622
1623         /* condition length should already be set as the default */
1624         break;
1625
1626     case BTM_FILTER_COND_BD_ADDR:
1627         p_cond = p_filt_cond->bdaddr_cond;
1628
1629         /* condition length should already be set as the default */
1630         break;
1631
1632     case BTM_CLR_INQUIRY_FILTER:
1633         condition_length = 0;
1634         break;
1635
1636     default:
1637         return (BTM_ILLEGAL_VALUE);     /* Bad parameter was passed in */
1638     }
1639
1640     btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1641
1642     /* Filter the inquiry results for the specified condition type and value */
1643     if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1644                                     p_cond, condition_length))
1645
1646     {
1647         return (BTM_CMD_STARTED);
1648     } else {
1649         return (BTM_NO_RESOURCES);
1650     }
1651 }
1652
1653
1654 /*******************************************************************************
1655 **
1656 ** Function         btm_event_filter_complete
1657 **
1658 ** Description      This function is called when a set event filter has completed.
1659 **                  Note: This routine currently only handles inquiry filters.
1660 **                      Connection filters are ignored for now.
1661 **
1662 ** Returns          void
1663 **
1664 *******************************************************************************/
1665 void btm_event_filter_complete (UINT8 *p)
1666 {
1667     UINT8            hci_status;
1668     tBTM_STATUS      status;
1669     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1670     tBTM_CMPL_CB   *p_cb = p_inq->p_inqfilter_cmpl_cb;
1671
1672 #if (BTM_INQ_DEBUG == TRUE)
1673     BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d\n",
1674                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1675 #endif
1676     /* If the filter complete event is from an old or cancelled request, ignore it */
1677     if (p_inq->pending_filt_complete_event) {
1678         p_inq->pending_filt_complete_event--;
1679         return;
1680     }
1681
1682     /* Only process the inquiry filter; Ignore the connection filter until it
1683        is used by the upper layers */
1684     if (p_inq->inqfilt_active == TRUE ) {
1685         /* Extract the returned status from the buffer */
1686         STREAM_TO_UINT8 (hci_status, p);
1687         if (hci_status != HCI_SUCCESS) {
1688             /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1689             BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)\n", hci_status);
1690             status = BTM_ERR_PROCESSING;
1691         } else {
1692             status = BTM_SUCCESS;
1693         }
1694
1695         /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1696            callback function to notify the initiator that it has completed */
1697         if (p_inq->state == BTM_INQ_INACTIVE_STATE) {
1698             p_inq->inqfilt_active = FALSE;
1699             if (p_cb) {
1700                 (*p_cb) (&status);
1701             }
1702         } else    /* An inquiry is active (the set filter command was internally generated),
1703                    process the next state of the process (Set a new filter or start the inquiry). */
1704         {
1705             if (status != BTM_SUCCESS) {
1706                 /* Process the inquiry complete (Error Status) */
1707                 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1708
1709                 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1710                 p_inq->inqfilt_active = FALSE;
1711                 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1712                 p_inq->state = BTM_INQ_INACTIVE_STATE;
1713
1714                 return;
1715             }
1716
1717             /* Check to see if a new filter needs to be set up */
1718             if (p_inq->state == BTM_INQ_CLR_FILT_STATE) {
1719                 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED) {
1720                     p_inq->state = BTM_INQ_SET_FILT_STATE;
1721                 } else { /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1722                     p_inq->inqfilt_active = FALSE;
1723
1724                     /* Process the inquiry complete (Error Status) */
1725                     btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1726                 }
1727             } else { /* Initiate the Inquiry or Periodic Inquiry */
1728                 p_inq->state = BTM_INQ_ACTIVE_STATE;
1729                 p_inq->inqfilt_active = FALSE;
1730                 btm_initiate_inquiry (p_inq);
1731             }
1732         }
1733     }
1734 }
1735
1736
1737 /*******************************************************************************
1738 **
1739 ** Function         btm_initiate_inquiry
1740 **
1741 ** Description      This function is called to start an inquiry or periodic inquiry
1742 **                  upon completion of the setting and/or clearing of the inquiry filter.
1743 **
1744 ** Inputs:          p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1745 **                      mode - GENERAL or LIMITED inquiry
1746 **                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1747 **                      max_resps - maximum amount of devices to search for before ending the inquiry
1748 **                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1749 **                                         BTM_FILTER_COND_BD_ADDR
1750 **                      filter_cond - value for the filter (based on filter_cond_type)
1751 **
1752 ** Returns          If an error occurs the initiator's callback is called with the error status.
1753 **
1754 *******************************************************************************/
1755 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1756 {
1757     const LAP       *lap;
1758     tBTM_INQ_PARMS  *p_inqparms = &p_inq->inqparms;
1759
1760 #if (BTM_INQ_DEBUG == TRUE)
1761     BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d\n",
1762                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1763 #endif
1764     btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1765
1766     if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) {
1767         btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1768         return;
1769     }
1770
1771     /* Make sure the number of responses doesn't overflow the database configuration */
1772     p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1773
1774     lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1775
1776     if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
1777         if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1778                                       p_inq->per_min_delay,
1779                                       *lap, p_inqparms->duration,
1780                                       p_inqparms->max_resps)) {
1781             btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1782         }
1783     } else {
1784         btm_clr_inq_result_flt();
1785
1786         /* Allocate memory to hold bd_addrs responding */
1787         if ((p_inq->p_bd_db = (tINQ_BDADDR *)osi_calloc(BT_DEFAULT_BUFFER_SIZE)) != NULL) {
1788             p_inq->max_bd_entries = (UINT16)(BT_DEFAULT_BUFFER_SIZE / sizeof(tINQ_BDADDR));
1789             /*            BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1790                                           p_inq->max_bd_entries); */
1791         }
1792
1793         if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0)) {
1794             btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1795         }
1796     }
1797 }
1798
1799 /*******************************************************************************
1800 **
1801 ** Function         btm_process_inq_results
1802 **
1803 ** Description      This function is called when inquiry results are received from
1804 **                  the device. It updates the inquiry database. If the inquiry
1805 **                  database is full, the oldest entry is discarded.
1806 **
1807 ** Parameters       inq_res_mode - BTM_INQ_RESULT_STANDARD
1808 **                                 BTM_INQ_RESULT_WITH_RSSI
1809 **                                 BTM_INQ_RESULT_EXTENDED
1810 **
1811 ** Returns          void
1812 **
1813 *******************************************************************************/
1814 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1815 {
1816     UINT8            num_resp, xx;
1817     BD_ADDR          bda;
1818     tINQ_DB_ENT     *p_i;
1819     tBTM_INQ_RESULTS *p_cur = NULL;
1820     BOOLEAN          is_new = TRUE;
1821     BOOLEAN          update = FALSE;
1822     INT8             i_rssi;
1823     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1824     tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1825     UINT8            page_scan_rep_mode = 0;
1826     UINT8            page_scan_per_mode = 0;
1827     UINT8            page_scan_mode = 0;
1828     UINT8            rssi = 0;
1829     DEV_CLASS        dc;
1830     UINT16           clock_offset;
1831     UINT8            *p_eir_data = NULL;
1832
1833 #if (BTM_INQ_DEBUG == TRUE)
1834     BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d inq_res_mode=%d\n",
1835                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active, inq_res_mode);
1836 #endif
1837     /* Only process the results if the BR inquiry is still active */
1838     if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK)) {
1839         return;
1840     }
1841
1842     STREAM_TO_UINT8 (num_resp, p);
1843
1844     for (xx = 0; xx < num_resp; xx++) {
1845         update = FALSE;
1846         /* Extract inquiry results */
1847         STREAM_TO_BDADDR   (bda, p);
1848         STREAM_TO_UINT8    (page_scan_rep_mode, p);
1849         STREAM_TO_UINT8    (page_scan_per_mode, p);
1850
1851         if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
1852             STREAM_TO_UINT8(page_scan_mode, p);
1853         }
1854
1855         STREAM_TO_DEVCLASS (dc, p);
1856         STREAM_TO_UINT16   (clock_offset, p);
1857         if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
1858             STREAM_TO_UINT8(rssi, p);
1859         }
1860
1861         p_i = btm_inq_db_find (bda);
1862
1863         /* Only process the num_resp is smaller than max_resps.
1864            If results are queued to BTU task while canceling inquiry,
1865            or when more than one result is in this response, > max_resp
1866            responses could be processed which can confuse some apps
1867         */
1868         if (p_inq->inqparms.max_resps &&
1869                 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1870 #if BLE_INCLUDED == TRUE
1871                 /* new device response */
1872                 && ( p_i == NULL ||
1873                      /* exisiting device with BR/EDR info */
1874                      (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1875                    )
1876 #endif
1877
1878            ) {
1879             BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring\n");
1880             return;
1881         }
1882
1883         /* Check if this address has already been processed for this inquiry */
1884         if (btm_inq_find_bdaddr(bda)) {
1885             BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]\n",
1886                             bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
1887             /* By default suppose no update needed */
1888             i_rssi = (INT8)rssi;
1889
1890             /* If this new RSSI is higher than the last one */
1891             if (p_inq->inqparms.report_dup && (rssi != 0) &&
1892                     p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1893 #if BLE_INCLUDED == TRUE
1894                             /* BR/EDR inquiry information update */
1895                             || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1896 #endif
1897                            )) {
1898                 p_cur = &p_i->inq_info.results;
1899                 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d\n", i_rssi, p_cur->rssi);
1900                 p_cur->rssi = i_rssi;
1901                 update = TRUE;
1902             }
1903             /* If we received a second Extended Inq Event for an already */
1904             /* discovered device, this is because for the first one EIR was not received */
1905             else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
1906                 p_cur = &p_i->inq_info.results;
1907                 update = TRUE;
1908             }
1909             /* If no update needed continue with next response (if any) */
1910             else {
1911                 continue;
1912             }
1913         }
1914
1915         /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
1916         if (p_i == NULL) {
1917             p_i = btm_inq_db_new (bda);
1918             is_new = TRUE;
1919         }
1920
1921         /* If an entry for the device already exists, overwrite it ONLY if it is from
1922            a previous inquiry. (Ignore it if it is a duplicate response from the same
1923            inquiry.
1924         */
1925         else if (p_i->inq_count == p_inq->inq_counter
1926 #if (BLE_INCLUDED == TRUE )
1927                  && (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR)
1928 #endif
1929                 ) {
1930             is_new = FALSE;
1931         }
1932
1933         /* keep updating RSSI to have latest value */
1934         if ( inq_res_mode != BTM_INQ_RESULT_STANDARD ) {
1935             p_i->inq_info.results.rssi = (INT8)rssi;
1936         } else {
1937             p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
1938         }
1939
1940         if (is_new == TRUE) {
1941             /* Save the info */
1942             p_cur = &p_i->inq_info.results;
1943             p_cur->page_scan_rep_mode = page_scan_rep_mode;
1944             p_cur->page_scan_per_mode = page_scan_per_mode;
1945             p_cur->page_scan_mode     = page_scan_mode;
1946             p_cur->dev_class[0]       = dc[0];
1947             p_cur->dev_class[1]       = dc[1];
1948             p_cur->dev_class[2]       = dc[2];
1949             p_cur->clock_offset       = clock_offset  | BTM_CLOCK_OFFSET_VALID;
1950
1951             p_i->time_of_resp = osi_time_get_os_boottime_ms();
1952
1953             if (p_i->inq_count != p_inq->inq_counter) {
1954                 p_inq->inq_cmpl_info.num_resp++;    /* A new response was found */
1955             }
1956
1957 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
1958             p_cur->inq_result_type    = BTM_INQ_RESULT_BR;
1959             if (p_i->inq_count != p_inq->inq_counter) {
1960                 p_cur->device_type  = BT_DEVICE_TYPE_BREDR;
1961                 p_i->scan_rsp       = FALSE;
1962             } else {
1963                 p_cur->device_type    |= BT_DEVICE_TYPE_BREDR;
1964             }
1965 #endif
1966             p_i->inq_count = p_inq->inq_counter;   /* Mark entry for current inquiry */
1967
1968             /* If the number of responses found and not unlimited, issue a cancel inquiry */
1969             if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
1970                     p_inq->inqparms.max_resps &&
1971                     p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
1972 #if BLE_INCLUDED == TRUE
1973                     /* BLE scanning is active and received adv */
1974                     && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
1975                          p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
1976                         (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
1977 #endif
1978                ) {
1979                 /*                BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
1980                 btsnd_hcic_inq_cancel();
1981
1982 #if BLE_INCLUDED == TRUE
1983                 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) {
1984                     btm_ble_stop_inquiry();
1985                 }
1986 #endif
1987                 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
1988             }
1989             /* Initialize flag to FALSE. This flag is set/used by application */
1990             p_i->inq_info.appl_knows_rem_name = FALSE;
1991         }
1992
1993         if (is_new || update) {
1994             if ( inq_res_mode == BTM_INQ_RESULT_EXTENDED ) {
1995                 memset( p_cur->eir_uuid, 0,
1996                         BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
1997                 /* set bit map of UUID list from received EIR */
1998                 btm_set_eir_uuid( p, p_cur );
1999                 p_eir_data = p;
2000             } else {
2001                 p_eir_data = NULL;
2002             }
2003
2004             /* If a callback is registered, call it with the results */
2005             if (p_inq_results_cb) {
2006                 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2007             }
2008         }
2009     }
2010 }
2011
2012 /*******************************************************************************
2013 **
2014 ** Function         btm_sort_inq_result
2015 **
2016 ** Description      This function is called when inquiry complete is received
2017 **                  from the device to sort inquiry results based on rssi.
2018 **
2019 ** Returns          void
2020 **
2021 *******************************************************************************/
2022 void btm_sort_inq_result(void)
2023 {
2024     UINT8               xx, yy, num_resp;
2025     tINQ_DB_ENT         *p_tmp  = NULL;
2026     tINQ_DB_ENT         *p_ent  = btm_cb.btm_inq_vars.inq_db;
2027     tINQ_DB_ENT         *p_next = btm_cb.btm_inq_vars.inq_db + 1;
2028     int                 size;
2029
2030     num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp < BTM_INQ_DB_SIZE) ?
2031                btm_cb.btm_inq_vars.inq_cmpl_info.num_resp : BTM_INQ_DB_SIZE;
2032
2033     if ((p_tmp = (tINQ_DB_ENT *)osi_malloc(sizeof(tINQ_DB_ENT))) != NULL) {
2034         size = sizeof(tINQ_DB_ENT);
2035         for (xx = 0; xx < num_resp - 1; xx++, p_ent++) {
2036             for (yy = xx + 1, p_next = p_ent + 1; yy < num_resp; yy++, p_next++) {
2037                 if (p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi) {
2038                     memcpy (p_tmp,  p_next, size);
2039                     memcpy (p_next, p_ent,  size);
2040                     memcpy (p_ent,  p_tmp,  size);
2041                 }
2042             }
2043         }
2044
2045         osi_free(p_tmp);
2046     }
2047 }
2048
2049 /*******************************************************************************
2050 **
2051 ** Function         btm_process_inq_complete
2052 **
2053 ** Description      This function is called when inquiry complete is received
2054 **                  from the device.  Call the callback if not in periodic inquiry
2055 **                  mode AND it is not NULL (The caller wants the event).
2056 **
2057 **                  The callback pass back the status and the number of responses
2058 **
2059 ** Returns          void
2060 **
2061 *******************************************************************************/
2062 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2063 {
2064     tBTM_CMPL_CB        *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2065     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2066
2067 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2068     /* inquiry inactive case happens when inquiry is cancelled.
2069        Make mode 0 for no further inquiries from the current inquiry process
2070     */
2071     if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH || !p_inq->inq_active) {
2072         /* re-initialize for next inquiry request */
2073         p_inq->next_state = BTM_BR_ONE;
2074         /* make the mode 0 here */
2075         p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2076
2077     }
2078 #endif
2079
2080 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2081     p_inq->inqparms.mode &= ~(mode);
2082 #endif
2083
2084     if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
2085         /*end of LE observe*/
2086         p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2087         p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2088         p_inq->scan_type = INQ_NONE;
2089     }
2090
2091
2092 #if (BTM_INQ_DEBUG == TRUE)
2093     BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d\n",
2094                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2095 #endif
2096     btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2097     /* Ignore any stray or late complete messages if the inquiry is not active */
2098     if (p_inq->inq_active) {
2099         p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2100
2101         /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2102         if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0) {
2103 #if BLE_INCLUDED == TRUE
2104             btm_clear_all_pending_le_entry();
2105 #endif
2106             p_inq->state = BTM_INQ_INACTIVE_STATE;
2107
2108             /* Increment so the start of a next inquiry has a new count */
2109             p_inq->inq_counter++;
2110
2111             btm_clr_inq_result_flt();
2112
2113             if ((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2114                     controller_get_interface()->supports_rssi_with_inquiry_results()) {
2115                 btm_sort_inq_result();
2116             }
2117
2118             /* Clear the results callback if set */
2119             p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2120             p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2121             p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2122
2123             /* If we have a callback registered for inquiry complete, call it */
2124             BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d\n",
2125                              p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2126
2127             if (p_inq_cb) {
2128                 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2129             }
2130         }
2131 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2132         if (p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
2133             /* make inquiry inactive for next iteration */
2134             p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2135             /* call the inquiry again */
2136             BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb, p_inq->p_inq_cmpl_cb);
2137         }
2138 #endif
2139     }
2140     if (p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL) { //this inquiry is complete
2141         p_inq->scan_type = INQ_NONE;
2142 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2143         /* check if the LE observe is pending */
2144         if (p_inq->p_inq_ble_results_cb != NULL) {
2145             BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2146             BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2147         }
2148 #endif
2149     }
2150 #if (BTM_INQ_DEBUG == TRUE)
2151     BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d\n",
2152                      btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2153 #endif
2154 }
2155
2156 /*******************************************************************************
2157 **
2158 ** Function         btm_process_cancel_complete
2159 **
2160 ** Description      This function is called when inquiry cancel complete is received
2161 **                  from the device.This function will also call the btm_process_inq_complete
2162 **                  This function is needed to differentiate a cancel_cmpl_evt from the
2163 **                  inq_cmpl_evt
2164 **
2165 ** Returns          void
2166 **
2167 *******************************************************************************/
2168 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2169 {
2170     btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2171     btm_process_inq_complete(status, mode);
2172 }
2173 /*******************************************************************************
2174 **
2175 ** Function         btm_initiate_rem_name
2176 **
2177 ** Description      This function looks initiates a remote name request.  It is called
2178 **                  either by GAP or by the API call BTM_ReadRemoteDeviceName.
2179 **
2180 ** Input Params:    p_cur         - pointer to an inquiry result structure (NULL if nonexistent)
2181 **                  p_cb            - callback function called when BTM_CMD_STARTED
2182 **                                    is returned.
2183 **                                    A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2184 **                                    callback.
2185 **
2186 ** Returns
2187 **                  BTM_CMD_STARTED is returned if the request was sent to HCI.
2188 **                  BTM_BUSY if already in progress
2189 **                  BTM_NO_RESOURCES if could not allocate resources to start the command
2190 **                  BTM_WRONG_MODE if the device is not up.
2191 **
2192 *******************************************************************************/
2193 tBTM_STATUS  btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2194                                     UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2195 {
2196     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2197     BOOLEAN              cmd_ok;
2198
2199
2200     /*** Make sure the device is ready ***/
2201     if (!BTM_IsDeviceUp()) {
2202         return (BTM_WRONG_MODE);
2203     }
2204
2205
2206     if (origin == BTM_RMT_NAME_SEC) {
2207         cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2208                                           HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2209         if (cmd_ok) {
2210             return BTM_CMD_STARTED;
2211         } else {
2212             return BTM_NO_RESOURCES;
2213         }
2214     }
2215     /* Make sure there are no two remote name requests from external API in progress */
2216     else if (origin == BTM_RMT_NAME_EXT) {
2217         if (p_inq->remname_active) {
2218             return (BTM_BUSY);
2219         } else {
2220             /* If there is no remote name request running,call the callback function and start timer */
2221             p_inq->p_remname_cmpl_cb = p_cb;
2222             memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2223             btu_start_timer (&p_inq->rmt_name_timer_ent,
2224                              BTU_TTYPE_BTM_RMT_NAME,
2225                              timeout);
2226
2227             /* If the database entry exists for the device, use its clock offset */
2228             if (p_cur) {
2229                 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2230                                                   p_cur->results.page_scan_rep_mode,
2231                                                   p_cur->results.page_scan_mode,
2232                                                   (UINT16)(p_cur->results.clock_offset |
2233                                                           BTM_CLOCK_OFFSET_VALID));
2234             } else { /* Otherwise use defaults and mark the clock offset as invalid */
2235                 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2236                                                   HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2237             }
2238             if (cmd_ok) {
2239                 p_inq->remname_active = TRUE;
2240                 return BTM_CMD_STARTED;
2241             } else {
2242                 return BTM_NO_RESOURCES;
2243             }
2244         }
2245     } else {
2246         return BTM_ILLEGAL_VALUE;
2247     }
2248 }
2249
2250 /*******************************************************************************
2251 **
2252 ** Function         btm_process_remote_name
2253 **
2254 ** Description      This function is called when a remote name is received from
2255 **                  the device. If remote names are cached, it updates the inquiry
2256 **                  database.
2257 **
2258 ** Returns          void
2259 **
2260 *******************************************************************************/
2261 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2262 {
2263     tBTM_REMOTE_DEV_NAME    rem_name;
2264     tBTM_INQUIRY_VAR_ST    *p_inq = &btm_cb.btm_inq_vars;
2265     tBTM_CMPL_CB           *p_cb = p_inq->p_remname_cmpl_cb;
2266     UINT8                  *p_n1;
2267
2268     UINT16                 temp_evt_len;
2269
2270     if (bda != NULL) {
2271         BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x\n", bda[0], bda[1],
2272                         bda[2], bda[3],
2273                         bda[4], bda[5]);
2274     }
2275
2276     BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x\n", p_inq->remname_bda[0], p_inq->remname_bda[1],
2277                     p_inq->remname_bda[2], p_inq->remname_bda[3],
2278                     p_inq->remname_bda[4], p_inq->remname_bda[5]);
2279
2280
2281
2282     /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2283     if ((p_inq->remname_active == TRUE) &&
2284             (((bda != NULL) &&
2285               (memcmp(bda, p_inq->remname_bda, BD_ADDR_LEN) == 0)) || bda == NULL))
2286
2287     {
2288 #if BLE_INCLUDED == TRUE
2289         if (BTM_UseLeLink(p_inq->remname_bda)) {
2290             if (hci_status == HCI_ERR_UNSPECIFIED) {
2291                 btm_ble_cancel_remote_name(p_inq->remname_bda);
2292             }
2293         }
2294 #endif
2295         btu_stop_timer (&p_inq->rmt_name_timer_ent);
2296         p_inq->remname_active = FALSE;
2297         /* Clean up and return the status if the command was not successful */
2298         /* Note: If part of the inquiry, the name is not stored, and the    */
2299         /*       inquiry complete callback is called.                       */
2300
2301         if (hci_status == HCI_SUCCESS) {
2302             /* Copy the name from the data stream into the return structure */
2303             /* Note that even if it is not being returned, it is used as a  */
2304             /*      temporary buffer.                                       */
2305             p_n1 = (UINT8 *)rem_name.remote_bd_name;
2306             rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2307             rem_name.remote_bd_name[rem_name.length] = 0;
2308             rem_name.status = BTM_SUCCESS;
2309             temp_evt_len = rem_name.length;
2310
2311             while (temp_evt_len > 0) {
2312                 *p_n1++ = *bdn++;
2313                 temp_evt_len--;
2314             }
2315             rem_name.remote_bd_name[rem_name.length] = 0;
2316         }
2317
2318
2319         /* If processing a stand alone remote name then report the error in the callback */
2320         else {
2321             rem_name.status = BTM_BAD_VALUE_RET;
2322             rem_name.length = 0;
2323             rem_name.remote_bd_name[0] = 0;
2324         }
2325         /* Reset the remote BAD to zero and call callback if possible */
2326         memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2327
2328         p_inq->p_remname_cmpl_cb = NULL;
2329         if (p_cb) {
2330             (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2331         }
2332     }
2333 }
2334
2335 /*******************************************************************************
2336 **
2337 ** Function         btm_inq_rmt_name_failed
2338 **
2339 ** Description      This function is if timeout expires while getting remote
2340 **                  name.  This is done for devices that incorrectly do not
2341 **                  report operation failure
2342 **
2343 ** Returns          void
2344 **
2345 *******************************************************************************/
2346 void btm_inq_rmt_name_failed (void)
2347 {
2348     BTM_TRACE_ERROR ("btm_inq_rmt_name_failed()  remname_active=%d\n", btm_cb.btm_inq_vars.remname_active);
2349
2350     if (btm_cb.btm_inq_vars.remname_active) {
2351         btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2352     } else {
2353         btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2354     }
2355 #if (SMP_INCLUDED == TRUE)
2356     btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2357 #endif  ///SMP_INCLUDED == TRUE
2358 }
2359 /*******************************************************************************
2360 **
2361 ** Function         btm_read_linq_tx_power_complete
2362 **
2363 ** Description      read inquiry tx power level complete callback function.
2364 **
2365 ** Returns          void
2366 **
2367 *******************************************************************************/
2368 void btm_read_linq_tx_power_complete(UINT8 *p)
2369 {
2370     tBTM_CMPL_CB                *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2371     tBTM_INQ_TXPWR_RESULTS        results;
2372
2373     btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2374     /* If there was a callback registered for read inq tx power, call it */
2375     btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2376
2377     if (p_cb) {
2378         STREAM_TO_UINT8  (results.hci_status, p);
2379
2380         if (results.hci_status == HCI_SUCCESS) {
2381             results.status = BTM_SUCCESS;
2382
2383             STREAM_TO_UINT8 (results.tx_power, p);
2384             BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n",
2385                              results.tx_power, results.hci_status);
2386         } else {
2387             results.status = BTM_ERR_PROCESSING;
2388         }
2389
2390         (*p_cb)(&results);
2391     }
2392
2393 }
2394 /*******************************************************************************
2395 **
2396 ** Function         BTM_WriteEIR
2397 **
2398 ** Description      This function is called to write EIR data to controller.
2399 **
2400 ** Parameters       p_buff - allocated HCI command buffer including extended
2401 **                           inquriry response
2402 **
2403 ** Returns          BTM_SUCCESS  - if successful
2404 **                  BTM_MODE_UNSUPPORTED - if local device cannot support it
2405 **
2406 *******************************************************************************/
2407 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2408 {
2409     if (controller_get_interface()->supports_extended_inquiry_response()) {
2410         BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
2411         btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2412         return BTM_SUCCESS;
2413     } else {
2414         osi_free(p_buff);
2415         return BTM_MODE_UNSUPPORTED;
2416     }
2417 }
2418
2419 /*******************************************************************************
2420 **
2421 ** Function         BTM_CheckEirData
2422 **
2423 ** Description      This function is called to get EIR data from significant part.
2424 **
2425 ** Parameters       p_eir - pointer of EIR significant part
2426 **                  type   - finding EIR data type
2427 **                  p_length - return the length of EIR data not including type
2428 **
2429 ** Returns          pointer of EIR data
2430 **
2431 *******************************************************************************/
2432 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2433 {
2434     UINT8 *p = p_eir;
2435     UINT8 length;
2436     UINT8 eir_type;
2437     BTM_TRACE_API("BTM_CheckEirData type=0x%02X\n", type);
2438
2439     STREAM_TO_UINT8(length, p);
2440     while ( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN)) {
2441         STREAM_TO_UINT8(eir_type, p);
2442         if ( eir_type == type ) {
2443             /* length doesn't include itself */
2444             *p_length = length - 1; /* minus the length of type */
2445             return p;
2446         }
2447         p += length - 1; /* skip the length of data */
2448         STREAM_TO_UINT8(length, p);
2449     }
2450
2451     *p_length = 0;
2452     return NULL;
2453 }
2454
2455 /*******************************************************************************
2456 **
2457 ** Function         btm_convert_uuid_to_eir_service
2458 **
2459 ** Description      This function is called to get the bit position of UUID.
2460 **
2461 ** Parameters       uuid16 - UUID 16-bit
2462 **
2463 ** Returns          BTM EIR service ID if found
2464 **                  BTM_EIR_MAX_SERVICES - if not found
2465 **
2466 *******************************************************************************/
2467 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2468 {
2469     UINT8 xx;
2470
2471     for ( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ ) {
2472         if ( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx]) {
2473             return xx;
2474         }
2475     }
2476     return BTM_EIR_MAX_SERVICES;
2477 }
2478
2479 /*******************************************************************************
2480 **
2481 ** Function         BTM_HasEirService
2482 **
2483 ** Description      This function is called to know if UUID in bit map of UUID.
2484 **
2485 ** Parameters       p_eir_uuid - bit map of UUID list
2486 **                  uuid16 - UUID 16-bit
2487 **
2488 ** Returns          TRUE - if found
2489 **                  FALSE - if not found
2490 **
2491 *******************************************************************************/
2492 BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2493 {
2494     UINT8 service_id;
2495
2496     service_id = btm_convert_uuid_to_eir_service(uuid16);
2497     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2498         return ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2499     } else {
2500         return ( FALSE );
2501     }
2502 }
2503
2504 /*******************************************************************************
2505 **
2506 ** Function         BTM_HasInquiryEirService
2507 **
2508 ** Description      This function is called to know if UUID in bit map of UUID list.
2509 **
2510 ** Parameters       p_results - inquiry results
2511 **                  uuid16 - UUID 16-bit
2512 **
2513 ** Returns          BTM_EIR_FOUND - if found
2514 **                  BTM_EIR_NOT_FOUND - if not found and it is complete list
2515 **                  BTM_EIR_UNKNOWN - if not found and it is not complete list
2516 **
2517 *******************************************************************************/
2518 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2519 {
2520     if ( BTM_HasEirService( p_results->eir_uuid, uuid16 )) {
2521         return BTM_EIR_FOUND;
2522     } else if ( p_results->eir_complete_list ) {
2523         return BTM_EIR_NOT_FOUND;
2524     } else {
2525         return BTM_EIR_UNKNOWN;
2526     }
2527 }
2528
2529 /*******************************************************************************
2530 **
2531 ** Function         BTM_AddEirService
2532 **
2533 ** Description      This function is called to add a service in bit map of UUID list.
2534 **
2535 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2536 **                  uuid16 - UUID 16-bit
2537 **
2538 ** Returns          None
2539 **
2540 *******************************************************************************/
2541 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2542 {
2543     UINT8 service_id;
2544
2545     service_id = btm_convert_uuid_to_eir_service(uuid16);
2546     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2547         BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2548     }
2549 }
2550
2551 /*******************************************************************************
2552 **
2553 ** Function         BTM_RemoveEirService
2554 **
2555 ** Description      This function is called to remove a service in bit map of UUID list.
2556 **
2557 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2558 **                  uuid16 - UUID 16-bit
2559 **
2560 ** Returns          None
2561 **
2562 *******************************************************************************/
2563 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2564 {
2565     UINT8 service_id;
2566
2567     service_id = btm_convert_uuid_to_eir_service(uuid16);
2568     if ( service_id < BTM_EIR_MAX_SERVICES ) {
2569         BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2570     }
2571 }
2572
2573 /*******************************************************************************
2574 **
2575 ** Function         BTM_GetEirSupportedServices
2576 **
2577 ** Description      This function is called to get UUID list from bit map of UUID list.
2578 **
2579 ** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2580 **                  p - reference of current pointer of EIR
2581 **                  max_num_uuid16 - max number of UUID can be written in EIR
2582 **                  num_uuid16 - number of UUID have been written in EIR
2583 **
2584 ** Returns          BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2585 **                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2586 **
2587 *******************************************************************************/
2588 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid,    UINT8 **p,
2589                                    UINT8  max_num_uuid16, UINT8 *p_num_uuid16)
2590 {
2591     UINT8 service_index;
2592
2593     *p_num_uuid16 = 0;
2594
2595     for (service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++) {
2596         if ( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index )) {
2597             if ( *p_num_uuid16 < max_num_uuid16 ) {
2598                 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2599                 (*p_num_uuid16)++;
2600             }
2601             /* if max number of UUIDs are stored and found one more */
2602             else {
2603                 return BTM_EIR_MORE_16BITS_UUID_TYPE;
2604             }
2605         }
2606     }
2607     return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2608 }
2609
2610 /*******************************************************************************
2611 **
2612 ** Function         BTM_GetEirUuidList
2613 **
2614 ** Description      This function parses EIR and returns UUID list.
2615 **
2616 ** Parameters       p_eir - EIR
2617 **                  uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2618 **                  p_num_uuid - return number of UUID in found list
2619 **                  p_uuid_list - return UUID list
2620 **                  max_num_uuid - maximum number of UUID to be returned
2621 **
2622 ** Returns          0 - if not found
2623 **                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2624 **                  BTM_EIR_MORE_16BITS_UUID_TYPE
2625 **                  BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2626 **                  BTM_EIR_MORE_32BITS_UUID_TYPE
2627 **                  BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2628 **                  BTM_EIR_MORE_128BITS_UUID_TYPE
2629 **
2630 *******************************************************************************/
2631 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2632                           UINT8 *p_uuid_list, UINT8 max_num_uuid)
2633 {
2634     UINT8   *p_uuid_data;
2635     UINT8   type;
2636     UINT8   yy, xx;
2637     UINT16  *p_uuid16 = (UINT16 *)p_uuid_list;
2638     UINT32  *p_uuid32 = (UINT32 *)p_uuid_list;
2639     char    buff[LEN_UUID_128 * 2 + 1];
2640
2641     p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2642     if ( p_uuid_data == NULL ) {
2643         return 0x00;
2644     }
2645
2646     if ( *p_num_uuid > max_num_uuid ) {
2647         BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d\n",
2648                           *p_num_uuid, max_num_uuid );
2649         *p_num_uuid = max_num_uuid;
2650     }
2651
2652     BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d\n", type, *p_num_uuid );
2653
2654     if ( uuid_size == LEN_UUID_16 ) {
2655         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2656             STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2657             BTM_TRACE_DEBUG("                     0x%04X\n", *(p_uuid16 + yy));
2658         }
2659     } else if ( uuid_size == LEN_UUID_32 ) {
2660         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2661             STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2662             BTM_TRACE_DEBUG("                     0x%08X\n", *(p_uuid32 + yy));
2663         }
2664     } else if ( uuid_size == LEN_UUID_128 ) {
2665         for ( yy = 0; yy < *p_num_uuid; yy++ ) {
2666             STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2667             for ( xx = 0; xx < LEN_UUID_128; xx++ ) {
2668                 sprintf(buff + xx * 2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2669             }
2670             BTM_TRACE_DEBUG("                     0x%s\n", buff);
2671         }
2672     }
2673
2674     return type;
2675 }
2676
2677
2678 /*******************************************************************************
2679 **
2680 ** Function         btm_eir_get_uuid_list
2681 **
2682 ** Description      This function searches UUID list in EIR.
2683 **
2684 ** Parameters       p_eir - address of EIR
2685 **                  uuid_size - size of UUID to find
2686 **                  p_num_uuid - number of UUIDs found
2687 **                  p_uuid_list_type - EIR data type
2688 **
2689 ** Returns          NULL - if UUID list with uuid_size is not found
2690 **                  beginning of UUID list in EIR - otherwise
2691 **
2692 *******************************************************************************/
2693 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2694                                      UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2695 {
2696     UINT8   *p_uuid_data;
2697     UINT8   complete_type, more_type;
2698     UINT8   uuid_len;
2699
2700     switch ( uuid_size ) {
2701     case LEN_UUID_16:
2702         complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2703         more_type     = BTM_EIR_MORE_16BITS_UUID_TYPE;
2704         break;
2705     case LEN_UUID_32:
2706         complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2707         more_type     = BTM_EIR_MORE_32BITS_UUID_TYPE;
2708         break;
2709     case LEN_UUID_128:
2710         complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2711         more_type     = BTM_EIR_MORE_128BITS_UUID_TYPE;
2712         break;
2713     default:
2714         *p_num_uuid = 0;
2715         return NULL;
2716         break;
2717     }
2718
2719     p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2720     if (p_uuid_data == NULL) {
2721         p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2722         *p_uuid_list_type = more_type;
2723     } else {
2724         *p_uuid_list_type = complete_type;
2725     }
2726
2727     *p_num_uuid = uuid_len / uuid_size;
2728     return p_uuid_data;
2729 }
2730
2731 /*******************************************************************************
2732 **
2733 ** Function         btm_convert_uuid_to_uuid16
2734 **
2735 ** Description      This function converts UUID to UUID 16-bit.
2736 **
2737 ** Parameters       p_uuid - address of UUID
2738 **                  uuid_size - size of UUID
2739 **
2740 ** Returns          0 - if UUID cannot be converted to UUID 16-bit
2741 **                  UUID 16-bit - otherwise
2742 **
2743 *******************************************************************************/
2744 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2745 {
2746     static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2747                                                    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2748                                                   };
2749     UINT16 uuid16 = 0;
2750     UINT32 uuid32;
2751     BOOLEAN is_base_uuid;
2752     UINT8  xx;
2753
2754     switch (uuid_size) {
2755     case LEN_UUID_16:
2756         STREAM_TO_UINT16 (uuid16, p_uuid);
2757         break;
2758     case LEN_UUID_32:
2759         STREAM_TO_UINT32 (uuid32, p_uuid);
2760         if (uuid32 < 0x10000) {
2761             uuid16 = (UINT16) uuid32;
2762         }
2763         break;
2764     case LEN_UUID_128:
2765         /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2766         is_base_uuid = TRUE;
2767         for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
2768             if (p_uuid[xx] != base_uuid[xx]) {
2769                 is_base_uuid = FALSE;
2770                 break;
2771             }
2772         }
2773         if (is_base_uuid) {
2774             if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0)) {
2775                 p_uuid += (LEN_UUID_128 - 4);
2776                 STREAM_TO_UINT16(uuid16, p_uuid);
2777             }
2778         }
2779         break;
2780     default:
2781         BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size\n");
2782         break;
2783     }
2784
2785     return ( uuid16);
2786 }
2787
2788 /*******************************************************************************
2789 **
2790 ** Function         btm_set_eir_uuid
2791 **
2792 ** Description      This function is called to store received UUID into inquiry result.
2793 **
2794 ** Parameters       p_eir - pointer of EIR significant part
2795 **                  p_results - pointer of inquiry result
2796 **
2797 ** Returns          None
2798 **
2799 *******************************************************************************/
2800 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2801 {
2802     UINT8   *p_uuid_data;
2803     UINT8   num_uuid;
2804     UINT16  uuid16;
2805     UINT8   yy;
2806     UINT8   type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2807
2808     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2809
2810     if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
2811         p_results->eir_complete_list = TRUE;
2812     } else {
2813         p_results->eir_complete_list = FALSE;
2814     }
2815
2816     BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X\n", p_results->eir_complete_list);
2817
2818     if ( p_uuid_data ) {
2819         for ( yy = 0; yy < num_uuid; yy++ ) {
2820             STREAM_TO_UINT16(uuid16, p_uuid_data);
2821             BTM_AddEirService( p_results->eir_uuid, uuid16 );
2822         }
2823     }
2824
2825     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2826     if ( p_uuid_data ) {
2827         for ( yy = 0; yy < num_uuid; yy++ ) {
2828             uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2829             p_uuid_data += LEN_UUID_32;
2830             if ( uuid16 ) {
2831                 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2832             }
2833         }
2834     }
2835
2836     p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2837     if ( p_uuid_data ) {
2838         for ( yy = 0; yy < num_uuid; yy++ ) {
2839             uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2840             p_uuid_data += LEN_UUID_128;
2841             if ( uuid16 ) {
2842                 BTM_AddEirService( p_results->eir_uuid, uuid16 );
2843             }
2844         }
2845     }
2846 }