btm_inq.c revision 5b69d6bf4a12cd161756396de47ec6b920c907db
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 <stdlib.h>
29#include <string.h>
30#include <stdio.h>
31#include <stddef.h>
32
33#include "bt_types.h"
34#include "controller.h"
35#include "gki.h"
36#include "hcimsgs.h"
37#include "btu.h"
38#include "btm_api.h"
39#include "btm_int.h"
40#include "hcidefs.h"
41
42#define BTM_INQ_REPLY_TIMEOUT   3       /* 3 second timeout waiting for responses */
43
44/* TRUE to enable DEBUG traces for btm_inq */
45#ifndef BTM_INQ_DEBUG
46#define BTM_INQ_DEBUG   FALSE
47#endif
48/********************************************************************************/
49/*                 L O C A L    D A T A    D E F I N I T I O N S                */
50/********************************************************************************/
51static const LAP general_inq_lap = {0x9e,0x8b,0x33};
52static const LAP limited_inq_lap = {0x9e,0x8b,0x00};
53
54const UINT16 BTM_EIR_UUID_LKUP_TBL[BTM_EIR_MAX_SERVICES] =
55{
56    UUID_SERVCLASS_SERVICE_DISCOVERY_SERVER,
57/*    UUID_SERVCLASS_BROWSE_GROUP_DESCRIPTOR,   */
58/*    UUID_SERVCLASS_PUBLIC_BROWSE_GROUP,       */
59    UUID_SERVCLASS_SERIAL_PORT,
60    UUID_SERVCLASS_LAN_ACCESS_USING_PPP,
61    UUID_SERVCLASS_DIALUP_NETWORKING,
62    UUID_SERVCLASS_IRMC_SYNC,
63    UUID_SERVCLASS_OBEX_OBJECT_PUSH,
64    UUID_SERVCLASS_OBEX_FILE_TRANSFER,
65    UUID_SERVCLASS_IRMC_SYNC_COMMAND,
66    UUID_SERVCLASS_HEADSET,
67    UUID_SERVCLASS_CORDLESS_TELEPHONY,
68    UUID_SERVCLASS_AUDIO_SOURCE,
69    UUID_SERVCLASS_AUDIO_SINK,
70    UUID_SERVCLASS_AV_REM_CTRL_TARGET,
71/*    UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION,    */
72    UUID_SERVCLASS_AV_REMOTE_CONTROL,
73/*    UUID_SERVCLASS_VIDEO_CONFERENCING,        */
74    UUID_SERVCLASS_INTERCOM,
75    UUID_SERVCLASS_FAX,
76    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
77/*    UUID_SERVCLASS_WAP,                       */
78/*    UUID_SERVCLASS_WAP_CLIENT,                */
79    UUID_SERVCLASS_PANU,
80    UUID_SERVCLASS_NAP,
81    UUID_SERVCLASS_GN,
82    UUID_SERVCLASS_DIRECT_PRINTING,
83/*    UUID_SERVCLASS_REFERENCE_PRINTING,        */
84    UUID_SERVCLASS_IMAGING,
85    UUID_SERVCLASS_IMAGING_RESPONDER,
86    UUID_SERVCLASS_IMAGING_AUTO_ARCHIVE,
87    UUID_SERVCLASS_IMAGING_REF_OBJECTS,
88    UUID_SERVCLASS_HF_HANDSFREE,
89    UUID_SERVCLASS_AG_HANDSFREE,
90    UUID_SERVCLASS_DIR_PRT_REF_OBJ_SERVICE,
91/*    UUID_SERVCLASS_REFLECTED_UI,              */
92    UUID_SERVCLASS_BASIC_PRINTING,
93    UUID_SERVCLASS_PRINTING_STATUS,
94    UUID_SERVCLASS_HUMAN_INTERFACE,
95    UUID_SERVCLASS_CABLE_REPLACEMENT,
96    UUID_SERVCLASS_HCRP_PRINT,
97    UUID_SERVCLASS_HCRP_SCAN,
98/*    UUID_SERVCLASS_COMMON_ISDN_ACCESS,        */
99/*    UUID_SERVCLASS_VIDEO_CONFERENCING_GW,     */
100/*    UUID_SERVCLASS_UDI_MT,                    */
101/*    UUID_SERVCLASS_UDI_TA,                    */
102/*    UUID_SERVCLASS_VCP,                       */
103    UUID_SERVCLASS_SAP,
104    UUID_SERVCLASS_PBAP_PCE,
105    UUID_SERVCLASS_PBAP_PSE,
106    UUID_SERVCLASS_PHONE_ACCESS,
107    UUID_SERVCLASS_HEADSET_HS,
108    UUID_SERVCLASS_PNP_INFORMATION,
109/*    UUID_SERVCLASS_GENERIC_NETWORKING,        */
110/*    UUID_SERVCLASS_GENERIC_FILETRANSFER,      */
111/*    UUID_SERVCLASS_GENERIC_AUDIO,             */
112/*    UUID_SERVCLASS_GENERIC_TELEPHONY,         */
113/*    UUID_SERVCLASS_UPNP_SERVICE,              */
114/*    UUID_SERVCLASS_UPNP_IP_SERVICE,           */
115/*    UUID_SERVCLASS_ESDP_UPNP_IP_PAN,          */
116/*    UUID_SERVCLASS_ESDP_UPNP_IP_LAP,          */
117/*    UUID_SERVCLASS_ESDP_UPNP_IP_L2CAP,        */
118    UUID_SERVCLASS_VIDEO_SOURCE,
119    UUID_SERVCLASS_VIDEO_SINK,
120/*    UUID_SERVCLASS_VIDEO_DISTRIBUTION         */
121    UUID_SERVCLASS_MESSAGE_ACCESS,
122    UUID_SERVCLASS_MESSAGE_NOTIFICATION,
123    UUID_SERVCLASS_HDP_SOURCE,
124    UUID_SERVCLASS_HDP_SINK
125};
126
127/********************************************************************************/
128/*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
129/********************************************************************************/
130static void         btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq);
131static tBTM_STATUS  btm_set_inq_event_filter (UINT8 filter_cond_type, tBTM_INQ_FILT_COND *p_filt_cond);
132static void         btm_clr_inq_result_flt (void);
133
134static UINT8        btm_convert_uuid_to_eir_service( UINT16 uuid16 );
135static void         btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results );
136static UINT8       *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
137                                           UINT8 *p_num_uuid, UINT8 *p_uuid_list_type );
138static UINT16       btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size );
139
140/*******************************************************************************
141**
142** Function         BTM_SetDiscoverability
143**
144** Description      This function is called to set the device into or out of
145**                  discoverable mode. Discoverable mode means inquiry
146**                  scans are enabled.  If a value of '0' is entered for window or
147**                  interval, the default values are used.
148**
149** Returns          BTM_SUCCESS if successful
150**                  BTM_BUSY if a setting of the filter is already in progress
151**                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
152**                  BTM_ILLEGAL_VALUE if a bad parameter was detected
153**                  BTM_WRONG_MODE if the device is not up.
154**
155*******************************************************************************/
156tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 interval)
157{
158    UINT8        scan_mode = 0;
159    UINT16       service_class;
160    UINT8       *p_cod;
161    UINT8        major, minor;
162    DEV_CLASS    cod;
163    LAP          temp_lap[2];
164    BOOLEAN      is_limited;
165    BOOLEAN      cod_limited;
166
167    BTM_TRACE_API ("BTM_SetDiscoverability");
168#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
169    if (controller_get_interface()->supports_ble())
170    {
171        if (btm_ble_set_discoverability((UINT16)(inq_mode))
172                            == BTM_SUCCESS)
173        {
174            btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
175            btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
176        }
177    }
178    inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
179#endif
180
181    /*** Check mode parameter ***/
182    if (inq_mode > BTM_MAX_DISCOVERABLE)
183        return (BTM_ILLEGAL_VALUE);
184
185    /* Make sure the controller is active */
186    if (!controller_get_interface()->get_is_ready())
187        return (BTM_DEV_RESET);
188
189    /* If the window and/or interval is '0', set to default values */
190    if (!window)
191        window = BTM_DEFAULT_DISC_WINDOW;
192
193    if (!interval)
194        interval = BTM_DEFAULT_DISC_INTERVAL;
195
196    BTM_TRACE_API ("BTM_SetDiscoverability: mode %d [NonDisc-0, Lim-1, Gen-2], window 0x%04x, interval 0x%04x",
197                        inq_mode, window, interval);
198
199    /*** Check for valid window and interval parameters ***/
200    /*** Only check window and duration if mode is connectable ***/
201    if (inq_mode != BTM_NON_DISCOVERABLE)
202    {
203        /* window must be less than or equal to interval */
204        if (window < HCI_MIN_INQUIRYSCAN_WINDOW     ||
205            window > HCI_MAX_INQUIRYSCAN_WINDOW     ||
206            interval < HCI_MIN_INQUIRYSCAN_INTERVAL ||
207            interval > HCI_MAX_INQUIRYSCAN_INTERVAL ||
208            window > interval)
209        {
210            return (BTM_ILLEGAL_VALUE);
211        }
212    }
213
214    /* Set the IAC if needed */
215    if (inq_mode != BTM_NON_DISCOVERABLE)
216    {
217        if (inq_mode & BTM_LIMITED_DISCOVERABLE)
218        {
219            /* Use the GIAC and LIAC codes for limited discoverable mode */
220            memcpy (temp_lap[0], limited_inq_lap, LAP_LEN);
221            memcpy (temp_lap[1], general_inq_lap, LAP_LEN);
222
223            if (!btsnd_hcic_write_cur_iac_lap (2, (LAP * const) temp_lap))
224                return (BTM_NO_RESOURCES);  /* Cannot continue */
225        }
226        else
227        {
228            if (!btsnd_hcic_write_cur_iac_lap (1, (LAP * const) &general_inq_lap))
229                return (BTM_NO_RESOURCES);  /* Cannot continue */
230        }
231
232        scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
233    }
234
235    /* Send down the inquiry scan window and period if changed */
236    if ((window != btm_cb.btm_inq_vars.inq_scan_window) ||
237        (interval != btm_cb.btm_inq_vars.inq_scan_period))
238    {
239        if (btsnd_hcic_write_inqscan_cfg (interval, window))
240        {
241            btm_cb.btm_inq_vars.inq_scan_window = window;
242            btm_cb.btm_inq_vars.inq_scan_period = interval;
243        }
244        else
245            return (BTM_NO_RESOURCES);
246    }
247
248    if (btm_cb.btm_inq_vars.connectable_mode & BTM_CONNECTABLE_MASK)
249        scan_mode |= HCI_PAGE_SCAN_ENABLED;
250
251    if (btsnd_hcic_write_scan_enable (scan_mode))
252    {
253        btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK);
254        btm_cb.btm_inq_vars.discoverable_mode |= inq_mode;
255    }
256    else
257        return (BTM_NO_RESOURCES);
258
259    /* Change the service class bit if mode has changed */
260    p_cod = BTM_ReadDeviceClass();
261    BTM_COD_SERVICE_CLASS(service_class, p_cod);
262    is_limited = (inq_mode & BTM_LIMITED_DISCOVERABLE) ? TRUE : FALSE;
263    cod_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? TRUE : FALSE;
264    if (is_limited ^ cod_limited)
265    {
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        FIELDS_TO_COD(cod, minor, major, service_class);
274        (void) BTM_SetDeviceClass (cod);
275    }
276
277    return (BTM_SUCCESS);
278}
279
280/*******************************************************************************
281**
282** Function         BTM_SetInquiryScanType
283**
284** Description      This function is called to set the iquiry scan-type to
285**                  standard or interlaced.
286**
287** Returns          BTM_SUCCESS if successful
288**                  BTM_MODE_UNSUPPORTED if not a 1.2 device
289**                  BTM_WRONG_MODE if the device is not up.
290**
291*******************************************************************************/
292tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type)
293{
294
295    BTM_TRACE_API ("BTM_SetInquiryScanType");
296    if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED)
297        return (BTM_ILLEGAL_VALUE);
298
299    /* whatever app wants if device is not 1.2 scan type should be STANDARD */
300    if (!controller_get_interface()->supports_interlaced_inquiry_scan())
301     return (BTM_MODE_UNSUPPORTED);
302
303    /* Check for scan type if configuration has been changed */
304    if (scan_type != btm_cb.btm_inq_vars.inq_scan_type)
305    {
306        if (BTM_IsDeviceUp())
307        {
308            if (btsnd_hcic_write_inqscan_type ((UINT8)scan_type))
309                btm_cb.btm_inq_vars.inq_scan_type = scan_type;
310            else
311                return (BTM_NO_RESOURCES);
312        }
313        else return (BTM_WRONG_MODE);
314    }
315    return (BTM_SUCCESS);
316}
317
318/*******************************************************************************
319**
320** Function         BTM_SetPageScanType
321**
322** Description      This function is called to set the page scan-type to
323**                  standard or interlaced.
324**
325** Returns          BTM_SUCCESS if successful
326**                  BTM_MODE_UNSUPPORTED if not a 1.2 device
327**                  BTM_WRONG_MODE if the device is not up.
328**
329*******************************************************************************/
330tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type)
331{
332    BTM_TRACE_API ("BTM_SetPageScanType");
333    if (scan_type != BTM_SCAN_TYPE_STANDARD && scan_type != BTM_SCAN_TYPE_INTERLACED)
334        return (BTM_ILLEGAL_VALUE);
335
336    /* whatever app wants if device is not 1.2 scan type should be STANDARD */
337    if (!controller_get_interface()->supports_interlaced_inquiry_scan())
338     return (BTM_MODE_UNSUPPORTED);
339
340    /* Check for scan type if configuration has been changed */
341    if (scan_type != btm_cb.btm_inq_vars.page_scan_type)
342    {
343        if (BTM_IsDeviceUp())
344        {
345            if (btsnd_hcic_write_pagescan_type ((UINT8)scan_type))
346                btm_cb.btm_inq_vars.page_scan_type  = scan_type;
347            else
348                return (BTM_NO_RESOURCES);
349        }
350        else return (BTM_WRONG_MODE);
351    }
352    return (BTM_SUCCESS);
353}
354
355
356/*******************************************************************************
357**
358** Function         BTM_SetInquiryMode
359**
360** Description      This function is called to set standard or with RSSI
361**                  mode of the inquiry for local device.
362**
363** Output Params:   mode - standard, with RSSI, extended
364**
365** Returns          BTM_SUCCESS if successful
366**                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
367**                  BTM_ILLEGAL_VALUE if a bad parameter was detected
368**                  BTM_WRONG_MODE if the device is not up.
369**
370*******************************************************************************/
371tBTM_STATUS BTM_SetInquiryMode (UINT8 mode)
372{
373    const controller_t *controller = controller_get_interface();
374    BTM_TRACE_API ("BTM_SetInquiryMode");
375    if (mode == BTM_INQ_RESULT_STANDARD)
376    {
377        /* mandatory mode */
378    }
379    else if (mode == BTM_INQ_RESULT_WITH_RSSI)
380    {
381        if (!controller->supports_rssi_with_inquiry_results())
382            return (BTM_MODE_UNSUPPORTED);
383    }
384    else if (mode == BTM_INQ_RESULT_EXTENDED)
385    {
386        if (!controller->supports_extended_inquiry_response())
387            return (BTM_MODE_UNSUPPORTED);
388    }
389    else
390        return (BTM_ILLEGAL_VALUE);
391
392    if (!BTM_IsDeviceUp())
393        return (BTM_WRONG_MODE);
394
395    if (!btsnd_hcic_write_inquiry_mode (mode))
396        return (BTM_NO_RESOURCES);
397
398    return (BTM_SUCCESS);
399}
400
401/*******************************************************************************
402**
403** Function         BTM_ReadDiscoverability
404**
405** Description      This function is called to read the current discoverability
406**                  mode of the device.
407**
408** Output Params:   p_window - current inquiry scan duration
409**                  p_interval - current inquiry scan interval
410**
411** Returns          BTM_NON_DISCOVERABLE, BTM_LIMITED_DISCOVERABLE, or
412**                  BTM_GENERAL_DISCOVERABLE
413**
414*******************************************************************************/
415UINT16 BTM_ReadDiscoverability (UINT16 *p_window, UINT16 *p_interval)
416{
417    BTM_TRACE_API ("BTM_ReadDiscoverability");
418    if (p_window)
419        *p_window = btm_cb.btm_inq_vars.inq_scan_window;
420
421    if (p_interval)
422        *p_interval = btm_cb.btm_inq_vars.inq_scan_period;
423
424    return (btm_cb.btm_inq_vars.discoverable_mode);
425}
426
427
428/*******************************************************************************
429**
430** Function         BTM_SetPeriodicInquiryMode
431**
432** Description      This function is called to set the device periodic inquiry mode.
433**                  If the duration is zero, the periodic inquiry mode is cancelled.
434**
435**                  Note: We currently do not allow concurrent inquiry and periodic inquiry.
436**
437** Parameters:      p_inqparms - pointer to the inquiry information
438**                      mode - GENERAL or LIMITED inquiry
439**                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
440**                      max_resps - maximum amount of devices to search for before ending the inquiry
441**                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
442**                                         BTM_FILTER_COND_BD_ADDR
443**                      filter_cond - value for the filter (based on filter_cond_type)
444**
445**                  max_delay - maximum amount of time between successive inquiries
446**                  min_delay - minimum amount of time between successive inquiries
447**                  p_results_cb - callback returning pointer to results (tBTM_INQ_RESULTS)
448**
449** Returns          BTM_CMD_STARTED if successfully started
450**                  BTM_ILLEGAL_VALUE if a bad parameter is detected
451**                  BTM_NO_RESOURCES if could not allocate a message buffer
452**                  BTM_SUCCESS - if cancelling the periodic inquiry
453**                  BTM_BUSY - if an inquiry is already active
454**                  BTM_WRONG_MODE if the device is not up.
455**
456*******************************************************************************/
457tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_delay,
458                                        UINT16 min_delay, tBTM_INQ_RESULTS_CB *p_results_cb)
459{
460    tBTM_STATUS  status;
461    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
462
463    BTM_TRACE_API ("BTM_SetPeriodicInquiryMode: mode: %d, dur: %d, rsps: %d, flt: %d, min: %d, max: %d",
464        p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
465        p_inqparms->filter_cond_type, min_delay, max_delay);
466
467    /*** Make sure the device is ready ***/
468    if (!BTM_IsDeviceUp())
469        return (BTM_WRONG_MODE);
470
471    /* Only one active inquiry is allowed in this implementation.
472       Also do not allow an inquiry if the inquiry filter is being updated */
473    if (p_inq->inq_active || p_inq->inqfilt_active)
474        return (BTM_BUSY);
475
476    /* If illegal parameters return FALSE */
477    if (p_inqparms->mode != BTM_GENERAL_INQUIRY &&
478        p_inqparms->mode != BTM_LIMITED_INQUIRY)
479        return (BTM_ILLEGAL_VALUE);
480
481    /* Verify the parameters for this command */
482    if (p_inqparms->duration < BTM_MIN_INQUIRY_LEN     ||
483        p_inqparms->duration > BTM_MAX_INQUIRY_LENGTH  ||
484        min_delay <= p_inqparms->duration              ||
485        min_delay < BTM_PER_INQ_MIN_MIN_PERIOD         ||
486        min_delay > BTM_PER_INQ_MAX_MIN_PERIOD         ||
487        max_delay <= min_delay                         ||
488        max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
489 /*       max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
490 /*  BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
491    {
492        return (BTM_ILLEGAL_VALUE);
493    }
494
495    /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
496    p_inq->inqparms = *p_inqparms;
497    p_inq->per_min_delay = min_delay;
498    p_inq->per_max_delay = max_delay;
499    p_inq->inq_cmpl_info.num_resp = 0;         /* Clear the results counter */
500    p_inq->p_inq_results_cb = p_results_cb;
501
502    p_inq->inq_active = (UINT8)((p_inqparms->mode == BTM_LIMITED_INQUIRY) ?
503                            (BTM_LIMITED_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE) :
504                            (BTM_GENERAL_INQUIRY_ACTIVE | BTM_PERIODIC_INQUIRY_ACTIVE));
505
506    /* If a filter is specified, then save it for later and clear the current filter.
507       The setting of the filter is done upon completion of clearing of the previous
508       filter.
509    */
510    if (p_inqparms->filter_cond_type != BTM_CLR_INQUIRY_FILTER)
511    {
512        p_inq->state = BTM_INQ_CLR_FILT_STATE;
513        p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
514    }
515    else    /* The filter is not being used so simply clear it; the inquiry can start after this operation */
516        p_inq->state = BTM_INQ_SET_FILT_STATE;
517
518    /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
519    if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type, &p_inqparms->filter_cond)) != BTM_CMD_STARTED)
520    {
521        /* If set filter command is not succesful reset the state */
522        p_inq->p_inq_results_cb = NULL;
523        p_inq->state = BTM_INQ_INACTIVE_STATE;
524
525    }
526
527    return (status);
528}
529
530
531/*******************************************************************************
532**
533** Function         BTM_CancelPeriodicInquiry
534**
535** Description      This function cancels a periodic inquiry
536**
537** Returns
538**                  BTM_NO_RESOURCES if could not allocate a message buffer
539**                  BTM_SUCCESS - if cancelling the periodic inquiry
540**                  BTM_WRONG_MODE if the device is not up.
541**
542*******************************************************************************/
543tBTM_STATUS BTM_CancelPeriodicInquiry(void)
544{
545    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
546    tBTM_STATUS          status = BTM_SUCCESS;
547    BTM_TRACE_API ("BTM_CancelPeriodicInquiry called");
548
549    /*** Make sure the device is ready ***/
550    if (!BTM_IsDeviceUp())
551        return (BTM_WRONG_MODE);
552
553    /* Only cancel if one is active */
554    if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
555    {
556        btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
557        btm_cb.btm_inq_vars.p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
558
559        if (!btsnd_hcic_exit_per_inq ())
560            status = BTM_NO_RESOURCES;
561
562        /* If the event filter is in progress, mark it so that the processing of the return
563           event will be ignored */
564        if(p_inq->inqfilt_active)
565            p_inq->pending_filt_complete_event++;
566
567        p_inq->inqfilt_active = FALSE;
568        p_inq->inq_counter++;
569    }
570
571    return (status);
572}
573
574
575/*******************************************************************************
576**
577** Function         BTM_SetConnectability
578**
579** Description      This function is called to set the device into or out of
580**                  connectable mode. Discoverable mode means page scans enabled.
581**
582** Returns          BTM_SUCCESS if successful
583**                  BTM_ILLEGAL_VALUE if a bad parameter is detected
584**                  BTM_NO_RESOURCES if could not allocate a message buffer
585**                  BTM_WRONG_MODE if the device is not up.
586**
587*******************************************************************************/
588tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 interval)
589{
590    UINT8    scan_mode = 0;
591    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
592
593    BTM_TRACE_API ("BTM_SetConnectability");
594
595#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
596    if (controller_get_interface()->supports_ble())
597    {
598        if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
599        {
600            return BTM_NO_RESOURCES;
601        }
602        p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
603        p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
604    }
605    page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
606#endif
607
608    /*** Check mode parameter ***/
609    if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE)
610        return (BTM_ILLEGAL_VALUE);
611
612    /* Make sure the controller is active */
613    if (!controller_get_interface()->get_is_ready())
614        return (BTM_DEV_RESET);
615
616    /* If the window and/or interval is '0', set to default values */
617    if (!window)
618        window = BTM_DEFAULT_CONN_WINDOW;
619
620    if (!interval)
621        interval = BTM_DEFAULT_CONN_INTERVAL;
622
623    BTM_TRACE_API ("BTM_SetConnectability: mode %d [NonConn-0, Conn-1], window 0x%04x, interval 0x%04x",
624                        page_mode, window, interval);
625
626    /*** Check for valid window and interval parameters ***/
627    /*** Only check window and duration if mode is connectable ***/
628    if (page_mode == BTM_CONNECTABLE)
629    {
630        /* window must be less than or equal to interval */
631        if (window < HCI_MIN_PAGESCAN_WINDOW     ||
632            window > HCI_MAX_PAGESCAN_WINDOW     ||
633            interval < HCI_MIN_PAGESCAN_INTERVAL ||
634            interval > HCI_MAX_PAGESCAN_INTERVAL ||
635            window > interval)
636        {
637            return (BTM_ILLEGAL_VALUE);
638        }
639
640        scan_mode |= HCI_PAGE_SCAN_ENABLED;
641    }
642
643    if ((window != p_inq->page_scan_window) ||
644        (interval != p_inq->page_scan_period))
645    {
646        p_inq->page_scan_window = window;
647        p_inq->page_scan_period = interval;
648        if (!btsnd_hcic_write_pagescan_cfg (interval, window))
649            return (BTM_NO_RESOURCES);
650    }
651
652    /* Keep the inquiry scan as previouosly set */
653    if (p_inq->discoverable_mode & BTM_DISCOVERABLE_MASK)
654        scan_mode |= HCI_INQUIRY_SCAN_ENABLED;
655
656    if (btsnd_hcic_write_scan_enable (scan_mode))
657    {
658        p_inq->connectable_mode &= (~BTM_CONNECTABLE_MASK);
659        p_inq->connectable_mode |= page_mode;
660
661        return (BTM_SUCCESS);
662    }
663
664    return (BTM_NO_RESOURCES);
665}
666
667
668/*******************************************************************************
669**
670** Function         BTM_ReadConnectability
671**
672** Description      This function is called to read the current discoverability
673**                  mode of the device.
674** Output Params    p_window - current page scan duration
675**                  p_interval - current time between page scans
676**
677** Returns          BTM_NON_CONNECTABLE or BTM_CONNECTABLE
678**
679*******************************************************************************/
680UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval)
681{
682    BTM_TRACE_API ("BTM_ReadConnectability");
683    if (p_window)
684        *p_window = btm_cb.btm_inq_vars.page_scan_window;
685
686    if (p_interval)
687        *p_interval = btm_cb.btm_inq_vars.page_scan_period;
688
689    return (btm_cb.btm_inq_vars.connectable_mode);
690}
691
692
693
694/*******************************************************************************
695**
696** Function         BTM_IsInquiryActive
697**
698** Description      This function returns a bit mask of the current inquiry state
699**
700** Returns          BTM_INQUIRY_INACTIVE if inactive (0)
701**                  BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active
702**                  BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active
703**                  BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active
704**
705*******************************************************************************/
706UINT16 BTM_IsInquiryActive (void)
707{
708    BTM_TRACE_API ("BTM_IsInquiryActive");
709
710    return(btm_cb.btm_inq_vars.inq_active);
711}
712
713
714
715/*******************************************************************************
716**
717** Function         BTM_CancelInquiry
718**
719** Description      This function cancels an inquiry if active
720**
721** Returns          BTM_SUCCESS if successful
722**                  BTM_NO_RESOURCES if could not allocate a message buffer
723**                  BTM_WRONG_MODE if the device is not up.
724**
725*******************************************************************************/
726tBTM_STATUS BTM_CancelInquiry(void)
727{
728    tBTM_STATUS           status = BTM_SUCCESS;
729    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
730#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
731    UINT8 active_mode=p_inq->inq_active;
732#endif
733    BTM_TRACE_API ("BTM_CancelInquiry called");
734
735    /*** Make sure the device is ready ***/
736    if (!BTM_IsDeviceUp())
737        return (BTM_WRONG_MODE);
738
739    /* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
740    if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
741        (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
742    {
743        p_inq->inq_active = BTM_INQUIRY_INACTIVE;
744        p_inq->state = BTM_INQ_INACTIVE_STATE;
745        p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; /* Do not notify caller anymore */
746        p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;    /* Do not notify caller anymore */
747
748        /* If the event filter is in progress, mark it so that the processing of the return
749            event will be ignored */
750        if (p_inq->inqfilt_active)
751        {
752            p_inq->inqfilt_active = FALSE;
753            p_inq->pending_filt_complete_event++;
754        }
755         /* Initiate the cancel inquiry */
756        else
757        {
758            if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
759#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
760            &&(active_mode & BTM_BR_INQUIRY_MASK)
761#endif
762            )
763            {
764                if (!btsnd_hcic_inq_cancel())
765                    status = BTM_NO_RESOURCES;
766            }
767#if BLE_INCLUDED == TRUE
768            if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
769#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
770            &&(active_mode & BTM_BLE_INQ_ACTIVE_MASK)
771#endif
772            )
773                btm_ble_stop_inquiry();
774#endif
775        }
776
777        /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
778         * and then send the BUSY_LEVEL event
779         * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
780         */
781
782         p_inq->inq_counter++;
783         btm_clr_inq_result_flt();
784    }
785
786    return (status);
787}
788
789
790/*******************************************************************************
791**
792** Function         BTM_StartInquiry
793**
794** Description      This function is called to start an inquiry.
795**
796** Parameters:      p_inqparms - pointer to the inquiry information
797**                      mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
798**                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
799**                      max_resps - maximum amount of devices to search for before ending the inquiry
800**                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
801**                                         BTM_FILTER_COND_BD_ADDR
802**                      filter_cond - value for the filter (based on filter_cond_type)
803**
804**                  p_results_cb   - Pointer to the callback routine which gets called
805**                                upon receipt of an inquiry result. If this field is
806**                                NULL, the application is not notified.
807**
808**                  p_cmpl_cb   - Pointer to the callback routine which gets called
809**                                upon completion.  If this field is NULL, the
810**                                application is not notified when completed.
811** Returns          tBTM_STATUS
812**                  BTM_CMD_STARTED if successfully initiated
813**                  BTM_BUSY if already in progress
814**                  BTM_ILLEGAL_VALUE if parameter(s) are out of range
815**                  BTM_NO_RESOURCES if could not allocate resources to start the command
816**                  BTM_WRONG_MODE if the device is not up.
817**
818*******************************************************************************/
819tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
820                              tBTM_CMPL_CB *p_cmpl_cb)
821{
822    tBTM_STATUS  status = BTM_CMD_STARTED;
823    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
824
825    BTM_TRACE_API ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
826                        p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
827                        p_inqparms->filter_cond_type);
828
829    /* Only one active inquiry is allowed in this implementation.
830       Also do not allow an inquiry if the inquiry filter is being updated */
831    if (p_inq->inq_active || p_inq->inqfilt_active)
832    {
833#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
834        /*check if LE observe is already running*/
835        if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL)
836        {
837            BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
838            p_inq->scan_type = INQ_GENERAL;
839            p_inq->inq_active = BTM_INQUIRY_INACTIVE;
840            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
841            btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
842        }
843        else
844#endif
845        {
846            return (BTM_BUSY);
847            BTM_TRACE_API("BTM_StartInquiry: return BUSY");
848        }
849    }
850    else
851        p_inq->scan_type = INQ_GENERAL;
852
853        /*** Make sure the device is ready ***/
854    if (!BTM_IsDeviceUp())
855        return (BTM_WRONG_MODE);
856
857    if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
858        (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
859#if (BLE_INCLUDED == TRUE)
860        && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
861        && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
862#endif
863        )
864        return (BTM_ILLEGAL_VALUE);
865
866#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
867        if(p_inq->next_state==BTM_FINISH)
868            return BTM_ILLEGAL_VALUE;
869#endif
870
871
872    /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
873    p_inq->inqparms = *p_inqparms;
874
875    /* Initialize the inquiry variables */
876    p_inq->state = BTM_INQ_ACTIVE_STATE;
877    p_inq->p_inq_cmpl_cb = p_cmpl_cb;
878    p_inq->p_inq_results_cb = p_results_cb;
879    p_inq->inq_cmpl_info.num_resp = 0;         /* Clear the results counter */
880    p_inq->inq_active = p_inqparms->mode;
881
882    BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
883
884/* interleave scan minimal conditions */
885#if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE))
886
887    /* check if both modes are present */
888    if((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) && (p_inqparms->mode & BTM_BR_INQUIRY_MASK))
889    {
890        BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
891        p_inqparms->duration=p_inqparms->intl_duration[p_inq->next_state];
892        p_inq->inqparms.duration=p_inqparms->duration;
893    }
894    else
895    {
896        BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x", p_inqparms->mode);
897        p_inq->next_state=BTM_NO_INTERLEAVING;
898    }
899#endif
900
901
902
903/* start LE inquiry here if requested */
904#if BLE_INCLUDED == TRUE
905    if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
906#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
907        &&(p_inq->next_state==BTM_BLE_ONE || p_inq->next_state==BTM_BLE_TWO ||
908           p_inq->next_state==BTM_NO_INTERLEAVING)
909#endif
910        )
911
912    {
913#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
914        p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
915        BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
916                       p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
917#endif
918        if (!controller_get_interface()->supports_ble())
919        {
920            p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
921            status = BTM_ILLEGAL_VALUE;
922        }
923        /* BLE for now does not support filter condition for inquiry */
924        else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
925                                            p_inqparms->duration)) != BTM_CMD_STARTED)
926        {
927            BTM_TRACE_ERROR("Err Starting LE Inquiry.");
928            p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
929        }
930#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
931        p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
932#endif
933
934#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
935        if(p_inq->next_state==BTM_NO_INTERLEAVING)
936        {
937            p_inq->next_state=BTM_FINISH;
938        }
939        else
940        {
941            BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d",
942                           p_inq->next_state+1);
943            p_inq->next_state+=1;
944        }
945        /* reset next_state if status <> BTM_Started */
946        if(status!=BTM_CMD_STARTED)
947            p_inq->next_state=BTM_BR_ONE;
948
949        /* if interleave scan..return here */
950        return status;
951#endif
952
953
954        BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
955    }
956#endif /* end of BLE_INCLUDED */
957
958    /* we're done with this routine if BR/EDR inquiry is not desired. */
959    if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
960        return status;
961
962    /* BR/EDR inquiry portion */
963#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
964    if((p_inq->next_state==BTM_BR_ONE || p_inq->next_state==BTM_BR_TWO ||
965        p_inq->next_state==BTM_NO_INTERLEAVING ))
966    {
967        p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
968#endif
969    /* If a filter is specified, then save it for later and clear the current filter.
970       The setting of the filter is done upon completion of clearing of the previous
971       filter.
972    */
973    switch (p_inqparms->filter_cond_type)
974    {
975    case BTM_CLR_INQUIRY_FILTER:
976        p_inq->state = BTM_INQ_SET_FILT_STATE;
977        break;
978
979    case BTM_FILTER_COND_DEVICE_CLASS:
980    case BTM_FILTER_COND_BD_ADDR:
981        /* The filter is not being used so simply clear it;
982            the inquiry can start after this operation */
983        p_inq->state = BTM_INQ_CLR_FILT_STATE;
984        p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
985        /* =============>>>> adding LE filtering here ????? */
986        break;
987
988    default:
989        return (BTM_ILLEGAL_VALUE);
990    }
991
992    /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
993    if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
994                                            &p_inqparms->filter_cond)) != BTM_CMD_STARTED)
995        p_inq->state = BTM_INQ_INACTIVE_STATE;
996
997#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
998        if (p_inq->next_state==BTM_NO_INTERLEAVING)
999            p_inq->next_state=BTM_FINISH;
1000        else
1001        {
1002            BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
1003                           p_inq->next_state+1);
1004            p_inq->next_state+=1;
1005        }
1006     }
1007     if (status!=BTM_CMD_STARTED)
1008     {
1009         /* Some error beginning the scan process.
1010            Reset the next_state parameter.. Do we need to reset the inq_active also?
1011         */
1012        BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x", status);
1013        p_inq->next_state=BTM_BR_ONE;
1014     }
1015#endif
1016
1017
1018    return (status);
1019}
1020
1021
1022/*******************************************************************************
1023**
1024** Function         BTM_ReadRemoteDeviceName
1025**
1026** Description      This function initiates a remote device HCI command to the
1027**                  controller and calls the callback when the process has completed.
1028**
1029** Input Params:    remote_bda      - device address of name to retrieve
1030**                  p_cb            - callback function called when BTM_CMD_STARTED
1031**                                    is returned.
1032**                                    A pointer to tBTM_REMOTE_DEV_NAME is passed to the
1033**                                    callback.
1034**
1035** Returns
1036**                  BTM_CMD_STARTED is returned if the request was successfully sent
1037**                                  to HCI.
1038**                  BTM_BUSY if already in progress
1039**                  BTM_UNKNOWN_ADDR if device address is bad
1040**                  BTM_NO_RESOURCES if could not allocate resources to start the command
1041**                  BTM_WRONG_MODE if the device is not up.
1042**
1043*******************************************************************************/
1044tBTM_STATUS  BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
1045                                                ,tBT_TRANSPORT transport)
1046{
1047    tBTM_INQ_INFO   *p_cur = NULL;
1048    tINQ_DB_ENT     *p_i;
1049
1050    BTM_TRACE_API ("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]",
1051               remote_bda[0], remote_bda[1], remote_bda[2],
1052               remote_bda[3], remote_bda[4], remote_bda[5]);
1053
1054    /* Use the remote device's clock offset if it is in the local inquiry database */
1055    if ((p_i = btm_inq_db_find (remote_bda)) != NULL)
1056    {
1057        p_cur = &p_i->inq_info;
1058    }
1059    BTM_TRACE_API ("no device found in inquiry db");
1060
1061#if (BLE_INCLUDED == TRUE)
1062    if (transport == BT_TRANSPORT_LE)
1063    {
1064        return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
1065    }
1066    else
1067#endif
1068
1069    return (btm_initiate_rem_name (remote_bda, p_cur, BTM_RMT_NAME_EXT,
1070                                   BTM_EXT_RMT_NAME_TIMEOUT, p_cb));
1071}
1072
1073/*******************************************************************************
1074**
1075** Function         BTM_CancelRemoteDeviceName
1076**
1077** Description      This function initiates the cancel request for the specified
1078**                  remote device.
1079**
1080** Input Params:    None
1081**
1082** Returns
1083**                  BTM_CMD_STARTED is returned if the request was successfully sent
1084**                                  to HCI.
1085**                  BTM_NO_RESOURCES if could not allocate resources to start the command
1086**                  BTM_WRONG_MODE if there is not an active remote name request.
1087**
1088*******************************************************************************/
1089tBTM_STATUS  BTM_CancelRemoteDeviceName (void)
1090{
1091    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1092
1093    BTM_TRACE_API ("BTM_CancelRemoteDeviceName()");
1094
1095    /* Make sure there is not already one in progress */
1096    if (p_inq->remname_active)
1097    {
1098#if BLE_INCLUDED == TRUE
1099        if (BTM_UseLeLink(p_inq->remname_bda))
1100        {
1101            if (btm_ble_cancel_remote_name(p_inq->remname_bda))
1102                return (BTM_CMD_STARTED);
1103            else
1104                return (BTM_UNKNOWN_ADDR);
1105        }
1106        else
1107#endif
1108        if (btsnd_hcic_rmt_name_req_cancel (p_inq->remname_bda))
1109            return (BTM_CMD_STARTED);
1110        else
1111            return (BTM_NO_RESOURCES);
1112    }
1113    else
1114        return (BTM_WRONG_MODE);
1115}
1116
1117/*******************************************************************************
1118**
1119** Function         BTM_InqDbRead
1120**
1121** Description      This function looks through the inquiry database for a match
1122**                  based on Bluetooth Device Address. This is the application's
1123**                  interface to get the inquiry details of a specific BD address.
1124**
1125** Returns          pointer to entry, or NULL if not found
1126**
1127*******************************************************************************/
1128tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
1129{
1130    BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]",
1131               p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
1132
1133    tINQ_DB_ENT *p_ent = btm_inq_db_find(p_bda);
1134    if (!p_ent)
1135      return NULL;
1136
1137    return &p_ent->inq_info;
1138}
1139
1140
1141/*******************************************************************************
1142**
1143** Function         BTM_InqDbFirst
1144**
1145** Description      This function looks through the inquiry database for the first
1146**                  used entry, and returns that. This is used in conjunction with
1147**                  BTM_InqDbNext by applications as a way to walk through the
1148**                  inquiry database.
1149**
1150** Returns          pointer to first in-use entry, or NULL if DB is empty
1151**
1152*******************************************************************************/
1153tBTM_INQ_INFO *BTM_InqDbFirst (void)
1154{
1155    UINT16       xx;
1156    tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1157
1158    for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1159    {
1160        if (p_ent->in_use)
1161            return (&p_ent->inq_info);
1162    }
1163
1164    /* If here, no used entry found */
1165    return ((tBTM_INQ_INFO *)NULL);
1166}
1167
1168
1169/*******************************************************************************
1170**
1171** Function         BTM_InqDbNext
1172**
1173** Description      This function looks through the inquiry database for the next
1174**                  used entry, and returns that.  If the input parameter is NULL,
1175**                  the first entry is returned.
1176**
1177** Returns          pointer to next in-use entry, or NULL if no more found.
1178**
1179*******************************************************************************/
1180tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur)
1181{
1182    tINQ_DB_ENT  *p_ent;
1183    UINT16        inx;
1184
1185    if (p_cur)
1186    {
1187        p_ent = (tINQ_DB_ENT *) ((UINT8 *)p_cur - offsetof (tINQ_DB_ENT, inq_info));
1188        inx = (UINT16)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1189
1190        for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++)
1191        {
1192            if (p_ent->in_use)
1193                return (&p_ent->inq_info);
1194        }
1195
1196        /* If here, more entries found */
1197        return ((tBTM_INQ_INFO *)NULL);
1198    }
1199    else
1200        return (BTM_InqDbFirst());
1201}
1202
1203
1204/*******************************************************************************
1205**
1206** Function         BTM_ClearInqDb
1207**
1208** Description      This function is called to clear out a device or all devices
1209**                  from the inquiry database.
1210**
1211** Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1212**                                              (NULL clears all entries)
1213**
1214** Returns          BTM_BUSY if an inquiry, get remote name, or event filter
1215**                          is active, otherwise BTM_SUCCESS
1216**
1217*******************************************************************************/
1218tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda)
1219{
1220    tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1221
1222    /* If an inquiry or remote name is in progress return busy */
1223    if (p_inq->inq_active != BTM_INQUIRY_INACTIVE ||
1224        p_inq->inqfilt_active)
1225        return (BTM_BUSY);
1226
1227    btm_clr_inq_db(p_bda);
1228
1229    return (BTM_SUCCESS);
1230}
1231
1232
1233/*******************************************************************************
1234**
1235** Function         BTM_ReadNumInqDbEntries
1236**
1237** Returns          This function returns the number of entries in the inquiry database.
1238**
1239*******************************************************************************/
1240UINT8 BTM_ReadNumInqDbEntries (void)
1241{
1242    UINT8         num_entries;
1243    UINT8         num_results;
1244    tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1245
1246    for (num_entries = 0, num_results = 0; num_entries < BTM_INQ_DB_SIZE; num_entries++, p_ent++)
1247    {
1248        if (p_ent->in_use)
1249            num_results++;
1250    }
1251
1252    return (num_results);
1253}
1254
1255/*******************************************************************************
1256**
1257** Function         BTM_ReadInquiryRspTxPower
1258**
1259** Description      This command will read the inquiry Transmit Power level used
1260**                  to transmit the FHS and EIR data packets.
1261**                  This can be used directly in the Tx Power Level EIR data type.
1262**
1263** Returns          BTM_SUCCESS if successful
1264**
1265*******************************************************************************/
1266tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb)
1267{
1268    if (btm_cb.devcb.p_txpwer_cmpl_cb)
1269        return (BTM_BUSY);
1270
1271     btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT );
1272
1273
1274    btm_cb.devcb.p_txpwer_cmpl_cb = p_cb;
1275
1276    if (!btsnd_hcic_read_inq_tx_power ())
1277    {
1278        btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
1279        btu_stop_timer (&btm_cb.devcb.txpwer_timer);
1280        return (BTM_NO_RESOURCES);
1281    }
1282    else
1283        return (BTM_CMD_STARTED);
1284}
1285/*******************************************************************************
1286**
1287** Function         BTM_WriteInquiryTxPower
1288**
1289** Description      This command is used to write the inquiry transmit power level
1290**                  used to transmit the inquiry (ID) data packets. The Controller
1291**                  should use the supported TX power level closest to the Tx_Power
1292**                  parameter.
1293**
1294** Returns          BTM_SUCCESS if successful
1295**
1296*******************************************************************************/
1297tBTM_STATUS  BTM_WriteInquiryTxPower (INT8 tx_power)
1298{
1299    tBTM_STATUS status = BTM_SUCCESS;
1300
1301    if (tx_power < BTM_MIN_INQ_TX_POWER || tx_power > BTM_MAX_INQ_TX_POWER)
1302    {
1303        status = BTM_ILLEGAL_VALUE;
1304    }
1305    else if (!btsnd_hcic_write_inq_tx_power(tx_power))
1306        status = BTM_NO_RESOURCES;
1307
1308    return status;
1309}
1310/*********************************************************************************
1311**********************************************************************************
1312**                                                                              **
1313**                      BTM Internal Inquiry Functions                          **
1314**                                                                              **
1315**********************************************************************************
1316*********************************************************************************/
1317/*******************************************************************************
1318**
1319** Function         btm_inq_db_reset
1320**
1321** Description      This function is called at at reset to clear the inquiry
1322**                  database & pending callback.
1323**
1324** Returns          void
1325**
1326*******************************************************************************/
1327void btm_inq_db_reset (void)
1328{
1329    tBTM_REMOTE_DEV_NAME     rem_name;
1330    tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1331    UINT8                    num_responses;
1332    UINT8                    temp_inq_active;
1333    tBTM_STATUS              status;
1334
1335    btu_stop_timer (&p_inq->inq_timer_ent);
1336
1337    /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
1338    if (p_inq->inq_active != BTM_INQUIRY_INACTIVE)
1339    {
1340        temp_inq_active = p_inq->inq_active;    /* Save so state can change BEFORE
1341                                                       callback is called */
1342        p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1343
1344        /* If not a periodic inquiry, the complete callback must be called to notify caller */
1345        if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
1346            temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE)
1347        {
1348            if (p_inq->p_inq_cmpl_cb)
1349            {
1350                num_responses = 0;
1351                (*p_inq->p_inq_cmpl_cb)(&num_responses);
1352            }
1353        }
1354    }
1355
1356    /* Cancel a remote name request if active, and notify the caller (if waiting) */
1357    if (p_inq->remname_active )
1358    {
1359        btu_stop_timer (&p_inq->rmt_name_timer_ent);
1360        p_inq->remname_active = FALSE;
1361        memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
1362
1363        if (p_inq->p_remname_cmpl_cb)
1364        {
1365            rem_name.status = BTM_DEV_RESET;
1366
1367            (*p_inq->p_remname_cmpl_cb)(&rem_name);
1368            p_inq->p_remname_cmpl_cb = NULL;
1369        }
1370    }
1371
1372    /* Cancel an inquiry filter request if active, and notify the caller (if waiting) */
1373    if (p_inq->inqfilt_active)
1374    {
1375        p_inq->inqfilt_active = FALSE;
1376
1377        if (p_inq->p_inqfilter_cmpl_cb)
1378        {
1379            status = BTM_DEV_RESET;
1380            (*p_inq->p_inqfilter_cmpl_cb)(&status);
1381        }
1382    }
1383
1384    p_inq->state = BTM_INQ_INACTIVE_STATE;
1385    p_inq->pending_filt_complete_event = 0;
1386    p_inq->p_inq_results_cb = NULL;
1387    btm_clr_inq_db(NULL);   /* Clear out all the entries in the database */
1388    btm_clr_inq_result_flt();
1389
1390    p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1391    p_inq->connectable_mode  = BTM_NON_CONNECTABLE;
1392    p_inq->page_scan_type    = BTM_SCAN_TYPE_STANDARD;
1393    p_inq->inq_scan_type     = BTM_SCAN_TYPE_STANDARD;
1394
1395#if BLE_INCLUDED == TRUE
1396    p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1397    p_inq->connectable_mode  |= BTM_BLE_NON_CONNECTABLE;
1398#endif
1399    return;
1400}
1401
1402
1403/*********************************************************************************
1404**
1405** Function         btm_inq_db_init
1406**
1407** Description      This function is called at startup to initialize the inquiry
1408**                  database.
1409**
1410** Returns          void
1411**
1412*******************************************************************************/
1413void btm_inq_db_init (void)
1414{
1415#if 0  /* cleared in btm_init; put back in if called from anywhere else! */
1416    memset (&btm_cb.btm_inq_vars, 0, sizeof (tBTM_INQUIRY_VAR_ST));
1417#endif
1418    btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1419}
1420
1421/*********************************************************************************
1422**
1423** Function         btm_inq_stop_on_ssp
1424**
1425** Description      This function is called on incoming SSP
1426**
1427** Returns          void
1428**
1429*******************************************************************************/
1430void btm_inq_stop_on_ssp(void)
1431{
1432    UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE);
1433
1434#if (BTM_INQ_DEBUG == TRUE)
1435    BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d",
1436        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);
1437#endif
1438    if (btm_cb.btm_inq_vars.no_inc_ssp)
1439    {
1440        if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE)
1441        {
1442            if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
1443            {
1444                BTM_CancelPeriodicInquiry();
1445            }
1446            else if (btm_cb.btm_inq_vars.inq_active & normal_active)
1447            {
1448                /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1449                btsnd_hcic_inq_cancel();
1450            }
1451        }
1452        /* do not allow inquiry to start */
1453        btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1454    }
1455}
1456
1457/*********************************************************************************
1458**
1459** Function         btm_inq_clear_ssp
1460**
1461** Description      This function is called when pairing_state becomes idle
1462**
1463** Returns          void
1464**
1465*******************************************************************************/
1466void btm_inq_clear_ssp(void)
1467{
1468    btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1469}
1470
1471/*********************************************************************************
1472**
1473** Function         btm_clr_inq_db
1474**
1475** Description      This function is called to clear out a device or all devices
1476**                  from the inquiry database.
1477**
1478** Parameter        p_bda - (input) BD_ADDR ->  Address of device to clear
1479**                                              (NULL clears all entries)
1480**
1481** Returns          void
1482**
1483*******************************************************************************/
1484void btm_clr_inq_db (BD_ADDR p_bda)
1485{
1486    tBTM_INQUIRY_VAR_ST     *p_inq = &btm_cb.btm_inq_vars;
1487    tINQ_DB_ENT             *p_ent = p_inq->inq_db;
1488    UINT16                   xx;
1489
1490#if (BTM_INQ_DEBUG == TRUE)
1491    BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d",
1492        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1493#endif
1494    for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1495    {
1496        if (p_ent->in_use)
1497        {
1498            /* If this is the specified BD_ADDR or clearing all devices */
1499            if (p_bda == NULL ||
1500                (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1501            {
1502                p_ent->in_use = FALSE;
1503            }
1504        }
1505    }
1506#if (BTM_INQ_DEBUG == TRUE)
1507    BTM_TRACE_DEBUG ("inq_active:0x%x state:%d",
1508        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1509#endif
1510}
1511
1512
1513/*******************************************************************************
1514**
1515** Function         btm_clr_inq_result_flt
1516**
1517** Description      This function looks through the bdaddr database for a match
1518**                  based on Bluetooth Device Address
1519**
1520** Returns          TRUE if found, else FALSE (new entry)
1521**
1522*******************************************************************************/
1523static void btm_clr_inq_result_flt (void)
1524{
1525    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1526
1527    if (p_inq->p_bd_db)
1528    {
1529        GKI_freebuf(p_inq->p_bd_db);
1530        p_inq->p_bd_db = NULL;
1531    }
1532    p_inq->num_bd_entries = 0;
1533    p_inq->max_bd_entries = 0;
1534}
1535
1536/*******************************************************************************
1537**
1538** Function         btm_inq_find_bdaddr
1539**
1540** Description      This function looks through the bdaddr database for a match
1541**                  based on Bluetooth Device Address
1542**
1543** Returns          TRUE if found, else FALSE (new entry)
1544**
1545*******************************************************************************/
1546BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1547{
1548    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1549    tINQ_BDADDR         *p_db = &p_inq->p_bd_db[0];
1550    UINT16       xx;
1551
1552    /* Don't bother searching, database doesn't exist or periodic mode */
1553    if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db)
1554        return (FALSE);
1555
1556    for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++)
1557    {
1558        if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1559            && p_db->inq_count == p_inq->inq_counter)
1560            return (TRUE);
1561    }
1562
1563    if (xx < p_inq->max_bd_entries)
1564    {
1565        p_db->inq_count = p_inq->inq_counter;
1566        memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1567        p_inq->num_bd_entries++;
1568    }
1569
1570    /* If here, New Entry */
1571    return (FALSE);
1572}
1573
1574/*******************************************************************************
1575**
1576** Function         btm_inq_db_find
1577**
1578** Description      This function looks through the inquiry database for a match
1579**                  based on Bluetooth Device Address
1580**
1581** Returns          pointer to entry, or NULL if not found
1582**
1583*******************************************************************************/
1584tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1585{
1586    UINT16       xx;
1587    tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1588
1589    for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1590    {
1591        if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1592            return (p_ent);
1593    }
1594
1595    /* If here, not found */
1596    return (NULL);
1597}
1598
1599
1600/*******************************************************************************
1601**
1602** Function         btm_inq_db_new
1603**
1604** Description      This function looks through the inquiry database for an unused
1605**                  entry. If no entry is free, it allocates the oldest entry.
1606**
1607** Returns          pointer to entry
1608**
1609*******************************************************************************/
1610tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1611{
1612    UINT16       xx;
1613    tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
1614    tINQ_DB_ENT  *p_old = btm_cb.btm_inq_vars.inq_db;
1615    UINT32       ot = 0xFFFFFFFF;
1616
1617    for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1618    {
1619        if (!p_ent->in_use)
1620        {
1621            memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1622            memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1623            p_ent->in_use = TRUE;
1624
1625            return (p_ent);
1626        }
1627
1628        if (p_ent->time_of_resp < ot)
1629        {
1630            p_old = p_ent;
1631            ot    = p_ent->time_of_resp;
1632        }
1633    }
1634
1635    /* If here, no free entry found. Return the oldest. */
1636
1637    memset (p_old, 0, sizeof (tINQ_DB_ENT));
1638    memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1639    p_old->in_use = TRUE;
1640
1641    return (p_old);
1642}
1643
1644
1645/*******************************************************************************
1646**
1647** Function         btm_set_inq_event_filter
1648**
1649** Description      This function is called to set the inquiry event filter.
1650**                  It is called by either internally, or by the external API function
1651**                  (BTM_SetInqEventFilter).  It is used internally as part of the
1652**                  inquiry processing.
1653**
1654** Input Params:
1655**                  filter_cond_type - this is the type of inquiry filter to apply:
1656**                          BTM_FILTER_COND_DEVICE_CLASS,
1657**                          BTM_FILTER_COND_BD_ADDR, or
1658**                          BTM_CLR_INQUIRY_FILTER
1659**
1660**                  p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1661**                          filter_cond_type  (See section 4.7.3 of Core Spec 1.0b).
1662**
1663** Returns          BTM_CMD_STARTED if successfully initiated
1664**                  BTM_NO_RESOURCES if couldn't get a memory pool buffer
1665**                  BTM_ILLEGAL_VALUE if a bad parameter was detected
1666**
1667*******************************************************************************/
1668static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1669                                             tBTM_INQ_FILT_COND *p_filt_cond)
1670{
1671    UINT8    condition_length = DEV_CLASS_LEN * 2;
1672    UINT8    condition_buf[DEV_CLASS_LEN * 2];
1673    UINT8   *p_cond = condition_buf;                    /* points to the condition to pass to HCI */
1674
1675#if (BTM_INQ_DEBUG == TRUE)
1676    BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
1677        filter_cond_type);
1678    BTM_TRACE_DEBUG ("                       condition [%02x%02x%02x %02x%02x%02x]",
1679               p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1680               p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1681#endif
1682
1683    /* Load the correct filter condition to pass to the lower layer */
1684    switch (filter_cond_type)
1685    {
1686    case BTM_FILTER_COND_DEVICE_CLASS:
1687        /* copy the device class and device class fields into contiguous memory to send to HCI */
1688        memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1689        memcpy (&condition_buf[DEV_CLASS_LEN],
1690                p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1691
1692        /* condition length should already be set as the default */
1693        break;
1694
1695    case BTM_FILTER_COND_BD_ADDR:
1696        p_cond = p_filt_cond->bdaddr_cond;
1697
1698        /* condition length should already be set as the default */
1699        break;
1700
1701    case BTM_CLR_INQUIRY_FILTER:
1702        condition_length = 0;
1703        break;
1704
1705    default:
1706        return (BTM_ILLEGAL_VALUE);     /* Bad parameter was passed in */
1707    }
1708
1709    btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1710
1711    /* Filter the inquiry results for the specified condition type and value */
1712    if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1713                                    p_cond, condition_length))
1714
1715        return (BTM_CMD_STARTED);
1716    else
1717        return (BTM_NO_RESOURCES);
1718}
1719
1720
1721/*******************************************************************************
1722**
1723** Function         btm_event_filter_complete
1724**
1725** Description      This function is called when a set event filter has completed.
1726**                  Note: This routine currently only handles inquiry filters.
1727**                      Connection filters are ignored for now.
1728**
1729** Returns          void
1730**
1731*******************************************************************************/
1732void btm_event_filter_complete (UINT8 *p)
1733{
1734    UINT8            hci_status;
1735    tBTM_STATUS      status;
1736    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1737    tBTM_CMPL_CB   *p_cb = p_inq->p_inqfilter_cmpl_cb;
1738
1739#if (BTM_INQ_DEBUG == TRUE)
1740    BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d",
1741        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1742#endif
1743    /* If the filter complete event is from an old or cancelled request, ignore it */
1744    if(p_inq->pending_filt_complete_event)
1745    {
1746        p_inq->pending_filt_complete_event--;
1747        return;
1748    }
1749
1750    /* Only process the inquiry filter; Ignore the connection filter until it
1751       is used by the upper layers */
1752    if (p_inq->inqfilt_active == TRUE )
1753    {
1754        /* Extract the returned status from the buffer */
1755        STREAM_TO_UINT8 (hci_status, p);
1756        if (hci_status != HCI_SUCCESS)
1757        {
1758            /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1759            BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)", hci_status);
1760            status = BTM_ERR_PROCESSING;
1761        }
1762        else
1763            status = BTM_SUCCESS;
1764
1765        /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1766           callback function to notify the initiator that it has completed */
1767        if (p_inq->state == BTM_INQ_INACTIVE_STATE)
1768        {
1769            p_inq->inqfilt_active = FALSE;
1770            if (p_cb)
1771                (*p_cb) (&status);
1772        }
1773        else    /* An inquiry is active (the set filter command was internally generated),
1774                   process the next state of the process (Set a new filter or start the inquiry). */
1775        {
1776            if(status != BTM_SUCCESS)
1777            {
1778                /* Process the inquiry complete (Error Status) */
1779                btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1780
1781                /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1782                p_inq->inqfilt_active = FALSE;
1783                p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1784                p_inq->state = BTM_INQ_INACTIVE_STATE;
1785
1786                return;
1787            }
1788
1789            /* Check to see if a new filter needs to be set up */
1790            if (p_inq->state == BTM_INQ_CLR_FILT_STATE)
1791            {
1792                if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED)
1793                {
1794                    p_inq->state = BTM_INQ_SET_FILT_STATE;
1795                }
1796                else    /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1797                {
1798                    p_inq->inqfilt_active = FALSE;
1799
1800                    /* Process the inquiry complete (Error Status) */
1801                    btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1802                }
1803            }
1804            else    /* Initiate the Inquiry or Periodic Inquiry */
1805            {
1806                p_inq->state = BTM_INQ_ACTIVE_STATE;
1807                p_inq->inqfilt_active = FALSE;
1808                btm_initiate_inquiry (p_inq);
1809            }
1810        }
1811    }
1812}
1813
1814
1815/*******************************************************************************
1816**
1817** Function         btm_initiate_inquiry
1818**
1819** Description      This function is called to start an inquiry or periodic inquiry
1820**                  upon completion of the setting and/or clearing of the inquiry filter.
1821**
1822** Inputs:          p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1823**                      mode - GENERAL or LIMITED inquiry
1824**                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1825**                      max_resps - maximum amount of devices to search for before ending the inquiry
1826**                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
1827**                                         BTM_FILTER_COND_BD_ADDR
1828**                      filter_cond - value for the filter (based on filter_cond_type)
1829**
1830** Returns          If an error occurs the initiator's callback is called with the error status.
1831**
1832*******************************************************************************/
1833static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
1834{
1835    const LAP       *lap;
1836    tBTM_INQ_PARMS  *p_inqparms = &p_inq->inqparms;
1837
1838#if (BTM_INQ_DEBUG == TRUE)
1839    BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d",
1840        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1841#endif
1842    btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
1843
1844    if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE)
1845    {
1846        btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1847        return;
1848    }
1849
1850    /* Make sure the number of responses doesn't overflow the database configuration */
1851    p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
1852
1853    lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
1854
1855    if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
1856    {
1857        if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
1858                                      p_inq->per_min_delay,
1859                                      *lap, p_inqparms->duration,
1860                                      p_inqparms->max_resps))
1861            btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1862    }
1863    else
1864    {
1865        btm_clr_inq_result_flt();
1866
1867        /* Allocate memory to hold bd_addrs responding */
1868        if ((p_inq->p_bd_db = (tINQ_BDADDR *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
1869        {
1870            p_inq->max_bd_entries = (UINT16)(GKI_MAX_BUF_SIZE / sizeof(tINQ_BDADDR));
1871            memset(p_inq->p_bd_db, 0, GKI_MAX_BUF_SIZE);
1872/*            BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
1873                              p_inq->max_bd_entries); */
1874        }
1875
1876        if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0))
1877            btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
1878    }
1879}
1880
1881/*******************************************************************************
1882**
1883** Function         btm_process_inq_results
1884**
1885** Description      This function is called when inquiry results are received from
1886**                  the device. It updates the inquiry database. If the inquiry
1887**                  database is full, the oldest entry is discarded.
1888**
1889** Parameters       inq_res_mode - BTM_INQ_RESULT_STANDARD
1890**                                 BTM_INQ_RESULT_WITH_RSSI
1891**                                 BTM_INQ_RESULT_EXTENDED
1892**
1893** Returns          void
1894**
1895*******************************************************************************/
1896void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
1897{
1898    UINT8            num_resp, xx;
1899    BD_ADDR          bda;
1900    tINQ_DB_ENT     *p_i;
1901    tBTM_INQ_RESULTS *p_cur=NULL;
1902    BOOLEAN          is_new = TRUE;
1903    BOOLEAN          update = FALSE;
1904    INT8             i_rssi;
1905    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1906    tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
1907    UINT8            page_scan_rep_mode = 0;
1908    UINT8            page_scan_per_mode = 0;
1909    UINT8            page_scan_mode = 0;
1910    UINT8            rssi = 0;
1911    DEV_CLASS        dc;
1912    UINT16           clock_offset;
1913    UINT8            *p_eir_data = NULL;
1914
1915#if (BTM_INQ_DEBUG == TRUE)
1916    BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
1917        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1918#endif
1919    /* Only process the results if the BR inquiry is still active */
1920    if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
1921        return;
1922
1923    STREAM_TO_UINT8 (num_resp, p);
1924
1925    for (xx = 0; xx < num_resp; xx++)
1926    {
1927        update = FALSE;
1928        /* Extract inquiry results */
1929        STREAM_TO_BDADDR   (bda, p);
1930        STREAM_TO_UINT8    (page_scan_rep_mode, p);
1931        STREAM_TO_UINT8    (page_scan_per_mode, p);
1932
1933        if (inq_res_mode == BTM_INQ_RESULT_STANDARD)
1934        {
1935            STREAM_TO_UINT8(page_scan_mode, p);
1936        }
1937
1938        STREAM_TO_DEVCLASS (dc, p);
1939        STREAM_TO_UINT16   (clock_offset, p);
1940        if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
1941        {
1942            STREAM_TO_UINT8(rssi, p);
1943        }
1944
1945        p_i = btm_inq_db_find (bda);
1946
1947        /* Only process the num_resp is smaller than max_resps.
1948           If results are queued to BTU task while canceling inquiry,
1949           or when more than one result is in this response, > max_resp
1950           responses could be processed which can confuse some apps
1951        */
1952        if (p_inq->inqparms.max_resps &&
1953            p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
1954#if BLE_INCLUDED == TRUE
1955            /* new device response */
1956            && ( p_i == NULL ||
1957                /* exisiting device with BR/EDR info */
1958                (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
1959               )
1960#endif
1961
1962            )
1963        {
1964/*            BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring"); */
1965            return;
1966        }
1967
1968        /* Check if this address has already been processed for this inquiry */
1969        if (btm_inq_find_bdaddr(bda))
1970        {
1971/*             BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]",
1972                             bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);*/
1973             /* By default suppose no update needed */
1974            i_rssi = (INT8)rssi;
1975
1976            /* If this new RSSI is higher than the last one */
1977            if(p_inq->inqparms.report_dup && (rssi != 0) &&
1978               p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
1979#if BLE_INCLUDED == TRUE
1980               /* BR/EDR inquiry information update */
1981                       || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
1982#endif
1983                       ))
1984            {
1985                p_cur = &p_i->inq_info.results;
1986                BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);
1987                p_cur->rssi = i_rssi;
1988                update = TRUE;
1989            }
1990            /* If we received a second Extended Inq Event for an already */
1991            /* discovered device, this is because for the first one EIR was not received */
1992            else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i))
1993            {
1994                p_cur = &p_i->inq_info.results;
1995                update = TRUE;
1996            }
1997            /* If no update needed continue with next response (if any) */
1998            else
1999                continue;
2000        }
2001
2002        /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
2003        if (p_i == NULL)
2004        {
2005            p_i = btm_inq_db_new (bda);
2006            is_new = TRUE;
2007        }
2008
2009        /* If an entry for the device already exists, overwrite it ONLY if it is from
2010           a previous inquiry. (Ignore it if it is a duplicate response from the same
2011           inquiry.
2012        */
2013        else if (p_i->inq_count == p_inq->inq_counter
2014#if (BLE_INCLUDED == TRUE )
2015            && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR)
2016#endif
2017            )
2018            is_new = FALSE;
2019
2020        /* keep updating RSSI to have latest value */
2021        if( inq_res_mode != BTM_INQ_RESULT_STANDARD )
2022            p_i->inq_info.results.rssi = (INT8)rssi;
2023        else
2024            p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
2025
2026        if (is_new == TRUE)
2027        {
2028            /* Save the info */
2029            p_cur = &p_i->inq_info.results;
2030            p_cur->page_scan_rep_mode = page_scan_rep_mode;
2031            p_cur->page_scan_per_mode = page_scan_per_mode;
2032            p_cur->page_scan_mode     = page_scan_mode;
2033            p_cur->dev_class[0]       = dc[0];
2034            p_cur->dev_class[1]       = dc[1];
2035            p_cur->dev_class[2]       = dc[2];
2036            p_cur->clock_offset       = clock_offset  | BTM_CLOCK_OFFSET_VALID;
2037
2038            p_i->time_of_resp = GKI_get_tick_count ();
2039
2040            if (p_i->inq_count != p_inq->inq_counter)
2041                p_inq->inq_cmpl_info.num_resp++;       /* A new response was found */
2042
2043#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2044            p_cur->inq_result_type    = BTM_INQ_RESULT_BR;
2045            if (p_i->inq_count != p_inq->inq_counter)
2046            {
2047                p_cur->device_type  = BT_DEVICE_TYPE_BREDR;
2048                p_i->scan_rsp       = FALSE;
2049            }
2050            else
2051                p_cur->device_type    |= BT_DEVICE_TYPE_BREDR;
2052#endif
2053                p_i->inq_count = p_inq->inq_counter;   /* Mark entry for current inquiry */
2054
2055            /* If the number of responses found and not unlimited, issue a cancel inquiry */
2056            if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
2057                p_inq->inqparms.max_resps &&
2058                p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
2059#if BLE_INCLUDED == TRUE
2060                /* BLE scanning is active and received adv */
2061                && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
2062                     p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
2063                    (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
2064#endif
2065                )
2066            {
2067/*                BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
2068                btsnd_hcic_inq_cancel();
2069
2070#if BLE_INCLUDED == TRUE
2071                if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
2072                    btm_ble_stop_inquiry();
2073#endif
2074                btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2075            }
2076            /* Initialize flag to FALSE. This flag is set/used by application */
2077            p_i->inq_info.appl_knows_rem_name = FALSE;
2078        }
2079
2080        if (is_new || update)
2081        {
2082            if( inq_res_mode == BTM_INQ_RESULT_EXTENDED )
2083            {
2084                memset( p_cur->eir_uuid, 0,
2085                        BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS/8));
2086                /* set bit map of UUID list from received EIR */
2087                btm_set_eir_uuid( p, p_cur );
2088                p_eir_data = p;
2089            }
2090            else
2091                p_eir_data = NULL;
2092
2093            /* If a callback is registered, call it with the results */
2094            if (p_inq_results_cb)
2095                (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2096        }
2097    }
2098}
2099
2100/*******************************************************************************
2101**
2102** Function         btm_sort_inq_result
2103**
2104** Description      This function is called when inquiry complete is received
2105**                  from the device to sort inquiry results based on rssi.
2106**
2107** Returns          void
2108**
2109*******************************************************************************/
2110void btm_sort_inq_result(void)
2111{
2112    UINT8               xx, yy, num_resp;
2113    tINQ_DB_ENT         *p_tmp  = NULL;
2114    tINQ_DB_ENT         *p_ent  = btm_cb.btm_inq_vars.inq_db;
2115    tINQ_DB_ENT         *p_next = btm_cb.btm_inq_vars.inq_db+1;
2116    int                 size;
2117
2118    num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp<BTM_INQ_DB_SIZE)?
2119                btm_cb.btm_inq_vars.inq_cmpl_info.num_resp: BTM_INQ_DB_SIZE;
2120
2121    if((p_tmp = (tINQ_DB_ENT *)GKI_getbuf(sizeof(tINQ_DB_ENT))) != NULL)
2122    {
2123        size = sizeof(tINQ_DB_ENT);
2124        for(xx = 0; xx < num_resp-1; xx++, p_ent++)
2125        {
2126            for(yy = xx+1, p_next = p_ent+1; yy < num_resp; yy++, p_next++)
2127            {
2128                if(p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi)
2129                {
2130                    memcpy (p_tmp,  p_next, size);
2131                    memcpy (p_next, p_ent,  size);
2132                    memcpy (p_ent,  p_tmp,  size);
2133                }
2134            }
2135        }
2136
2137        GKI_freebuf(p_tmp);
2138    }
2139}
2140
2141/*******************************************************************************
2142**
2143** Function         btm_process_inq_complete
2144**
2145** Description      This function is called when inquiry complete is received
2146**                  from the device.  Call the callback if not in periodic inquiry
2147**                  mode AND it is not NULL (The caller wants the event).
2148**
2149**                  The callback pass back the status and the number of responses
2150**
2151** Returns          void
2152**
2153*******************************************************************************/
2154void btm_process_inq_complete (UINT8 status, UINT8 mode)
2155{
2156    tBTM_CMPL_CB        *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2157    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2158
2159#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2160    /* inquiry inactive case happens when inquiry is cancelled.
2161       Make mode 0 for no further inquiries from the current inquiry process
2162    */
2163    if(status!=HCI_SUCCESS || p_inq->next_state==BTM_FINISH || !p_inq->inq_active)
2164    {
2165        /* re-initialize for next inquiry request */
2166        p_inq->next_state=BTM_BR_ONE;
2167        /* make the mode 0 here */
2168        p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2169
2170    }
2171#endif
2172
2173#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2174    p_inq->inqparms.mode &= ~(mode);
2175#endif
2176
2177    if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active)
2178    {
2179        /*end of LE observe*/
2180        p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2181        p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2182        p_inq->scan_type=INQ_NONE;
2183    }
2184
2185
2186#if (BTM_INQ_DEBUG == TRUE)
2187    BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d",
2188        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2189#endif
2190    btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2191    /* Ignore any stray or late complete messages if the inquiry is not active */
2192    if (p_inq->inq_active)
2193    {
2194        p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2195
2196        /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2197        if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)
2198        {
2199            p_inq->state = BTM_INQ_INACTIVE_STATE;
2200
2201            /* Increment so the start of a next inquiry has a new count */
2202            p_inq->inq_counter++;
2203
2204            btm_clr_inq_result_flt();
2205
2206            if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2207                controller_get_interface()->supports_rssi_with_inquiry_results())
2208            {
2209                btm_sort_inq_result();
2210            }
2211
2212            /* Clear the results callback if set */
2213            p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2214            p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2215            p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2216
2217            /* If we have a callback registered for inquiry complete, call it */
2218            BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d",
2219                        p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2220
2221            if (p_inq_cb)
2222                (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2223        }
2224#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2225        if(p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))
2226        {
2227            /* make inquiry inactive for next iteration */
2228            p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2229            /* call the inquiry again */
2230            BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
2231        }
2232#endif
2233    }
2234    if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
2235    {
2236        p_inq->scan_type = INQ_NONE;
2237#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2238        /* check if the LE observe is pending */
2239        if(p_inq->p_inq_ble_results_cb != NULL)
2240        {
2241            BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2242            BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2243        }
2244#endif
2245    }
2246#if (BTM_INQ_DEBUG == TRUE)
2247    BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d",
2248        btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2249#endif
2250}
2251
2252/*******************************************************************************
2253**
2254** Function         btm_process_cancel_complete
2255**
2256** Description      This function is called when inquiry cancel complete is received
2257**                  from the device.This function will also call the btm_process_inq_complete
2258**                  This function is needed to differentiate a cancel_cmpl_evt from the
2259**                  inq_cmpl_evt
2260**
2261** Returns          void
2262**
2263*******************************************************************************/
2264void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2265{
2266     btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2267     btm_process_inq_complete(status, mode);
2268}
2269/*******************************************************************************
2270**
2271** Function         btm_initiate_rem_name
2272**
2273** Description      This function looks initiates a remote name request.  It is called
2274**                  either by GAP or by the API call BTM_ReadRemoteDeviceName.
2275**
2276** Input Params:    p_cur         - pointer to an inquiry result structure (NULL if nonexistent)
2277**                  p_cb            - callback function called when BTM_CMD_STARTED
2278**                                    is returned.
2279**                                    A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2280**                                    callback.
2281**
2282** Returns
2283**                  BTM_CMD_STARTED is returned if the request was sent to HCI.
2284**                  BTM_BUSY if already in progress
2285**                  BTM_NO_RESOURCES if could not allocate resources to start the command
2286**                  BTM_WRONG_MODE if the device is not up.
2287**
2288*******************************************************************************/
2289tBTM_STATUS  btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2290                                    UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2291{
2292    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2293    BOOLEAN              cmd_ok;
2294
2295
2296    /*** Make sure the device is ready ***/
2297    if (!BTM_IsDeviceUp())
2298        return (BTM_WRONG_MODE);
2299
2300
2301    if (origin == BTM_RMT_NAME_SEC)
2302    {
2303        cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2304                                         HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2305        if (cmd_ok)
2306            return BTM_CMD_STARTED;
2307        else
2308            return BTM_NO_RESOURCES;
2309    }
2310    /* Make sure there are no two remote name requests from external API in progress */
2311    else if (origin == BTM_RMT_NAME_EXT)
2312    {
2313        if (p_inq->remname_active)
2314        {
2315            return (BTM_BUSY);
2316        }
2317        else
2318        {
2319            /* If there is no remote name request running,call the callback function and start timer */
2320            p_inq->p_remname_cmpl_cb = p_cb;
2321            memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2322            btu_start_timer (&p_inq->rmt_name_timer_ent,
2323                             BTU_TTYPE_BTM_RMT_NAME,
2324                             timeout);
2325
2326            /* If the database entry exists for the device, use its clock offset */
2327            if (p_cur)
2328            {
2329                cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2330                                         p_cur->results.page_scan_rep_mode,
2331                                         p_cur->results.page_scan_mode,
2332                                         (UINT16)(p_cur->results.clock_offset |
2333                                                  BTM_CLOCK_OFFSET_VALID));
2334            }
2335            else /* Otherwise use defaults and mark the clock offset as invalid */
2336            {
2337                cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2338                                         HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2339            }
2340            if (cmd_ok)
2341            {
2342                p_inq->remname_active = TRUE;
2343                return BTM_CMD_STARTED;
2344            }
2345            else
2346                return BTM_NO_RESOURCES;
2347        }
2348    }
2349    else
2350    {
2351        return BTM_ILLEGAL_VALUE;
2352    }
2353}
2354
2355/*******************************************************************************
2356**
2357** Function         btm_process_remote_name
2358**
2359** Description      This function is called when a remote name is received from
2360**                  the device. If remote names are cached, it updates the inquiry
2361**                  database.
2362**
2363** Returns          void
2364**
2365*******************************************************************************/
2366void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2367{
2368    tBTM_REMOTE_DEV_NAME    rem_name;
2369    tBTM_INQUIRY_VAR_ST    *p_inq = &btm_cb.btm_inq_vars;
2370    tBTM_CMPL_CB           *p_cb = p_inq->p_remname_cmpl_cb;
2371    UINT8                  *p_n1;
2372
2373    UINT16                 temp_evt_len;
2374
2375    if (bda != NULL)
2376    {
2377        BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x",bda[0], bda[1],
2378                 bda[2], bda[3],
2379                 bda[4], bda[5]);
2380    }
2381
2382    BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x",p_inq->remname_bda[0], p_inq->remname_bda[1],
2383             p_inq->remname_bda[2], p_inq->remname_bda[3],
2384             p_inq->remname_bda[4], p_inq->remname_bda[5]);
2385
2386
2387
2388    /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2389    if ((p_inq->remname_active ==TRUE)&&
2390        (((bda != NULL) &&
2391        (memcmp(bda, p_inq->remname_bda,BD_ADDR_LEN)==0)) || bda == NULL))
2392
2393    {
2394#if BLE_INCLUDED == TRUE
2395        if (BTM_UseLeLink(p_inq->remname_bda))
2396        {
2397            if (hci_status == HCI_ERR_UNSPECIFIED)
2398                btm_ble_cancel_remote_name(p_inq->remname_bda);
2399        }
2400#endif
2401        btu_stop_timer (&p_inq->rmt_name_timer_ent);
2402        p_inq->remname_active = FALSE;
2403         /* Clean up and return the status if the command was not successful */
2404         /* Note: If part of the inquiry, the name is not stored, and the    */
2405         /*       inquiry complete callback is called.                       */
2406
2407        if ((hci_status == HCI_SUCCESS))
2408        {
2409            /* Copy the name from the data stream into the return structure */
2410            /* Note that even if it is not being returned, it is used as a  */
2411            /*      temporary buffer.                                       */
2412            p_n1 = (UINT8 *)rem_name.remote_bd_name;
2413            rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2414            rem_name.remote_bd_name[rem_name.length] = 0;
2415            rem_name.status = BTM_SUCCESS;
2416            temp_evt_len = rem_name.length;
2417
2418            while (temp_evt_len > 0)
2419            {
2420                *p_n1++ = *bdn++;
2421                temp_evt_len--;
2422            }
2423            rem_name.remote_bd_name[rem_name.length] = 0;
2424        }
2425
2426
2427        /* If processing a stand alone remote name then report the error in the callback */
2428        else
2429        {
2430            rem_name.status = BTM_BAD_VALUE_RET;
2431            rem_name.length = 0;
2432            rem_name.remote_bd_name[0] = 0;
2433        }
2434        /* Reset the remote BAD to zero and call callback if possible */
2435        memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2436
2437        p_inq->p_remname_cmpl_cb = NULL;
2438        if (p_cb)
2439            (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2440    }
2441}
2442
2443/*******************************************************************************
2444**
2445** Function         btm_inq_rmt_name_failed
2446**
2447** Description      This function is if timeout expires while getting remote
2448**                  name.  This is done for devices that incorrectly do not
2449**                  report operation failure
2450**
2451** Returns          void
2452**
2453*******************************************************************************/
2454void btm_inq_rmt_name_failed (void)
2455{
2456    BTM_TRACE_ERROR ("btm_inq_rmt_name_failed()  remname_active=%d", btm_cb.btm_inq_vars.remname_active);
2457
2458    if (btm_cb.btm_inq_vars.remname_active)
2459        btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2460    else
2461        btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2462
2463    btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2464}
2465/*******************************************************************************
2466**
2467** Function         btm_read_linq_tx_power_complete
2468**
2469** Description      read inquiry tx power level complete callback function.
2470**
2471** Returns          void
2472**
2473*******************************************************************************/
2474void btm_read_linq_tx_power_complete(UINT8 *p)
2475{
2476    tBTM_CMPL_CB                *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2477    tBTM_INQ_TXPWR_RESULTS        results;
2478
2479    btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2480    /* If there was a callback registered for read inq tx power, call it */
2481    btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2482
2483    if (p_cb)
2484    {
2485        STREAM_TO_UINT8  (results.hci_status, p);
2486
2487        if (results.hci_status == HCI_SUCCESS)
2488        {
2489            results.status = BTM_SUCCESS;
2490
2491            STREAM_TO_UINT8 (results.tx_power, p);
2492            BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x",
2493                              results.tx_power, results.hci_status);
2494        }
2495        else
2496            results.status = BTM_ERR_PROCESSING;
2497
2498        (*p_cb)(&results);
2499    }
2500
2501}
2502/*******************************************************************************
2503**
2504** Function         BTM_WriteEIR
2505**
2506** Description      This function is called to write EIR data to controller.
2507**
2508** Parameters       p_buff - allocated HCI command buffer including extended
2509**                           inquriry response
2510**
2511** Returns          BTM_SUCCESS  - if successful
2512**                  BTM_MODE_UNSUPPORTED - if local device cannot support it
2513**
2514*******************************************************************************/
2515tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2516{
2517    if (controller_get_interface()->supports_extended_inquiry_response())
2518    {
2519        BTM_TRACE_API("Write Extended Inquiry Response to controller");
2520        btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2521        return BTM_SUCCESS;
2522    }
2523    else
2524    {
2525        GKI_freebuf(p_buff);
2526        return BTM_MODE_UNSUPPORTED;
2527    }
2528}
2529
2530/*******************************************************************************
2531**
2532** Function         BTM_CheckEirData
2533**
2534** Description      This function is called to get EIR data from significant part.
2535**
2536** Parameters       p_eir - pointer of EIR significant part
2537**                  type   - finding EIR data type
2538**                  p_length - return the length of EIR data not including type
2539**
2540** Returns          pointer of EIR data
2541**
2542*******************************************************************************/
2543UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2544{
2545    UINT8 *p = p_eir;
2546    UINT8 length;
2547    UINT8 eir_type;
2548    BTM_TRACE_API("BTM_CheckEirData type=0x%02X", type);
2549
2550    STREAM_TO_UINT8(length, p);
2551    while( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN))
2552    {
2553        STREAM_TO_UINT8(eir_type, p);
2554        if( eir_type == type )
2555        {
2556            /* length doesn't include itself */
2557            *p_length = length - 1; /* minus the length of type */
2558            return p;
2559        }
2560        p += length - 1; /* skip the length of data */
2561        STREAM_TO_UINT8(length, p);
2562    }
2563
2564    *p_length = 0;
2565    return NULL;
2566}
2567
2568/*******************************************************************************
2569**
2570** Function         btm_convert_uuid_to_eir_service
2571**
2572** Description      This function is called to get the bit position of UUID.
2573**
2574** Parameters       uuid16 - UUID 16-bit
2575**
2576** Returns          BTM EIR service ID if found
2577**                  BTM_EIR_MAX_SERVICES - if not found
2578**
2579*******************************************************************************/
2580static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2581{
2582    UINT8 xx;
2583
2584    for( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ )
2585    {
2586        if( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx])
2587        {
2588            return xx;
2589        }
2590    }
2591    return BTM_EIR_MAX_SERVICES;
2592}
2593
2594/*******************************************************************************
2595**
2596** Function         BTM_HasEirService
2597**
2598** Description      This function is called to know if UUID in bit map of UUID.
2599**
2600** Parameters       p_eir_uuid - bit map of UUID list
2601**                  uuid16 - UUID 16-bit
2602**
2603** Returns          TRUE - if found
2604**                  FALSE - if not found
2605**
2606*******************************************************************************/
2607BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2608{
2609    UINT8 service_id;
2610
2611    service_id = btm_convert_uuid_to_eir_service(uuid16);
2612    if( service_id < BTM_EIR_MAX_SERVICES )
2613        return( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
2614    else
2615        return( FALSE );
2616}
2617
2618/*******************************************************************************
2619**
2620** Function         BTM_HasInquiryEirService
2621**
2622** Description      This function is called to know if UUID in bit map of UUID list.
2623**
2624** Parameters       p_results - inquiry results
2625**                  uuid16 - UUID 16-bit
2626**
2627** Returns          BTM_EIR_FOUND - if found
2628**                  BTM_EIR_NOT_FOUND - if not found and it is complete list
2629**                  BTM_EIR_UNKNOWN - if not found and it is not complete list
2630**
2631*******************************************************************************/
2632tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
2633{
2634    if( BTM_HasEirService( p_results->eir_uuid, uuid16 ))
2635    {
2636        return BTM_EIR_FOUND;
2637    }
2638    else if( p_results->eir_complete_list )
2639    {
2640        return BTM_EIR_NOT_FOUND;
2641    }
2642    else
2643        return BTM_EIR_UNKNOWN;
2644}
2645
2646/*******************************************************************************
2647**
2648** Function         BTM_AddEirService
2649**
2650** Description      This function is called to add a service in bit map of UUID list.
2651**
2652** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2653**                  uuid16 - UUID 16-bit
2654**
2655** Returns          None
2656**
2657*******************************************************************************/
2658void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2659{
2660    UINT8 service_id;
2661
2662    service_id = btm_convert_uuid_to_eir_service(uuid16);
2663    if( service_id < BTM_EIR_MAX_SERVICES )
2664        BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
2665}
2666
2667/*******************************************************************************
2668**
2669** Function         BTM_RemoveEirService
2670**
2671** Description      This function is called to remove a service in bit map of UUID list.
2672**
2673** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2674**                  uuid16 - UUID 16-bit
2675**
2676** Returns          None
2677**
2678*******************************************************************************/
2679void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
2680{
2681    UINT8 service_id;
2682
2683    service_id = btm_convert_uuid_to_eir_service(uuid16);
2684    if( service_id < BTM_EIR_MAX_SERVICES )
2685        BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
2686}
2687
2688/*******************************************************************************
2689**
2690** Function         BTM_GetEirSupportedServices
2691**
2692** Description      This function is called to get UUID list from bit map of UUID list.
2693**
2694** Parameters       p_eir_uuid - bit mask of UUID list for EIR
2695**                  p - reference of current pointer of EIR
2696**                  max_num_uuid16 - max number of UUID can be written in EIR
2697**                  num_uuid16 - number of UUID have been written in EIR
2698**
2699** Returns          BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
2700**                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
2701**
2702*******************************************************************************/
2703UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid,    UINT8 **p,
2704                                   UINT8  max_num_uuid16, UINT8 *p_num_uuid16)
2705{
2706    UINT8 service_index;
2707
2708    *p_num_uuid16 = 0;
2709
2710    for(service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++)
2711    {
2712        if( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index ))
2713        {
2714            if( *p_num_uuid16 < max_num_uuid16 )
2715            {
2716                UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
2717                (*p_num_uuid16)++;
2718            }
2719            /* if max number of UUIDs are stored and found one more */
2720            else
2721            {
2722                return BTM_EIR_MORE_16BITS_UUID_TYPE;
2723            }
2724        }
2725    }
2726    return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2727}
2728
2729/*******************************************************************************
2730**
2731** Function         BTM_GetEirUuidList
2732**
2733** Description      This function parses EIR and returns UUID list.
2734**
2735** Parameters       p_eir - EIR
2736**                  uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
2737**                  p_num_uuid - return number of UUID in found list
2738**                  p_uuid_list - return UUID list
2739**                  max_num_uuid - maximum number of UUID to be returned
2740**
2741** Returns          0 - if not found
2742**                  BTM_EIR_COMPLETE_16BITS_UUID_TYPE
2743**                  BTM_EIR_MORE_16BITS_UUID_TYPE
2744**                  BTM_EIR_COMPLETE_32BITS_UUID_TYPE
2745**                  BTM_EIR_MORE_32BITS_UUID_TYPE
2746**                  BTM_EIR_COMPLETE_128BITS_UUID_TYPE
2747**                  BTM_EIR_MORE_128BITS_UUID_TYPE
2748**
2749*******************************************************************************/
2750UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
2751                            UINT8 *p_uuid_list, UINT8 max_num_uuid)
2752{
2753    UINT8   *p_uuid_data;
2754    UINT8   type;
2755    UINT8   yy, xx;
2756    UINT16  *p_uuid16 = (UINT16 *)p_uuid_list;
2757    UINT32  *p_uuid32 = (UINT32 *)p_uuid_list;
2758    char    buff[LEN_UUID_128 * 2 + 1];
2759
2760    p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
2761    if( p_uuid_data == NULL )
2762    {
2763        return 0x00;
2764    }
2765
2766    if( *p_num_uuid > max_num_uuid )
2767    {
2768        BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d",
2769                           *p_num_uuid, max_num_uuid );
2770        *p_num_uuid = max_num_uuid;
2771    }
2772
2773    BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d", type, *p_num_uuid );
2774
2775    if( uuid_size == LEN_UUID_16 )
2776    {
2777        for( yy = 0; yy < *p_num_uuid; yy++ )
2778        {
2779            STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
2780            BTM_TRACE_DEBUG("                     0x%04X", *(p_uuid16 + yy));
2781        }
2782    }
2783    else if( uuid_size == LEN_UUID_32 )
2784    {
2785        for( yy = 0; yy < *p_num_uuid; yy++ )
2786        {
2787            STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
2788            BTM_TRACE_DEBUG("                     0x%08X", *(p_uuid32 + yy));
2789        }
2790    }
2791    else if( uuid_size == LEN_UUID_128 )
2792    {
2793        for( yy = 0; yy < *p_num_uuid; yy++ )
2794        {
2795            STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
2796            for( xx = 0; xx < LEN_UUID_128; xx++ )
2797                sprintf(buff + xx*2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
2798            BTM_TRACE_DEBUG("                     0x%s", buff);
2799        }
2800    }
2801
2802    return type;
2803}
2804
2805
2806/*******************************************************************************
2807**
2808** Function         btm_eir_get_uuid_list
2809**
2810** Description      This function searches UUID list in EIR.
2811**
2812** Parameters       p_eir - address of EIR
2813**                  uuid_size - size of UUID to find
2814**                  p_num_uuid - number of UUIDs found
2815**                  p_uuid_list_type - EIR data type
2816**
2817** Returns          NULL - if UUID list with uuid_size is not found
2818**                  beginning of UUID list in EIR - otherwise
2819**
2820*******************************************************************************/
2821static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
2822                                     UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
2823{
2824    UINT8   *p_uuid_data;
2825    UINT8   complete_type, more_type;
2826    UINT8   uuid_len;
2827
2828    switch( uuid_size )
2829    {
2830    case LEN_UUID_16:
2831        complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
2832        more_type     = BTM_EIR_MORE_16BITS_UUID_TYPE;
2833        break;
2834    case LEN_UUID_32:
2835        complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
2836        more_type     = BTM_EIR_MORE_32BITS_UUID_TYPE;
2837        break;
2838    case LEN_UUID_128:
2839        complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
2840        more_type     = BTM_EIR_MORE_128BITS_UUID_TYPE;
2841        break;
2842    default:
2843        *p_num_uuid = 0;
2844        return NULL;
2845        break;
2846    }
2847
2848    p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
2849    if(p_uuid_data == NULL)
2850    {
2851        p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
2852        *p_uuid_list_type = more_type;
2853    }
2854    else
2855    {
2856        *p_uuid_list_type = complete_type;
2857    }
2858
2859    *p_num_uuid = uuid_len / uuid_size;
2860    return p_uuid_data;
2861}
2862
2863/*******************************************************************************
2864**
2865** Function         btm_convert_uuid_to_uuid16
2866**
2867** Description      This function converts UUID to UUID 16-bit.
2868**
2869** Parameters       p_uuid - address of UUID
2870**                  uuid_size - size of UUID
2871**
2872** Returns          0 - if UUID cannot be converted to UUID 16-bit
2873**                  UUID 16-bit - otherwise
2874**
2875*******************************************************************************/
2876static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
2877{
2878    static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
2879                                                   0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2880    UINT16 uuid16 = 0;
2881    UINT32 uuid32;
2882    BOOLEAN is_base_uuid;
2883    UINT8  xx;
2884
2885    switch (uuid_size)
2886    {
2887    case LEN_UUID_16:
2888        STREAM_TO_UINT16 (uuid16, p_uuid);
2889        break;
2890    case LEN_UUID_32:
2891        STREAM_TO_UINT32 (uuid32, p_uuid);
2892        if (uuid32 < 0x10000)
2893            uuid16 = (UINT16) uuid32;
2894        break;
2895    case LEN_UUID_128:
2896        /* See if we can compress his UUID down to 16 or 32bit UUIDs */
2897        is_base_uuid = TRUE;
2898        for (xx = 0; xx < LEN_UUID_128 - 4; xx++)
2899        {
2900            if (p_uuid[xx] != base_uuid[xx])
2901            {
2902                is_base_uuid = FALSE;
2903                break;
2904            }
2905        }
2906        if (is_base_uuid)
2907        {
2908            if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0))
2909            {
2910                p_uuid += (LEN_UUID_128 - 4);
2911                STREAM_TO_UINT16(uuid16, p_uuid);
2912            }
2913        }
2914        break;
2915    default:
2916        BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size");
2917        break;
2918    }
2919
2920    return( uuid16);
2921}
2922
2923/*******************************************************************************
2924**
2925** Function         btm_set_eir_uuid
2926**
2927** Description      This function is called to store received UUID into inquiry result.
2928**
2929** Parameters       p_eir - pointer of EIR significant part
2930**                  p_results - pointer of inquiry result
2931**
2932** Returns          None
2933**
2934*******************************************************************************/
2935void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
2936{
2937    UINT8   *p_uuid_data;
2938    UINT8   num_uuid;
2939    UINT16  uuid16;
2940    UINT8   yy;
2941    UINT8   type = BTM_EIR_MORE_16BITS_UUID_TYPE;
2942
2943    p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
2944
2945    if(type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE)
2946    {
2947        p_results->eir_complete_list = TRUE;
2948    }
2949    else
2950    {
2951        p_results->eir_complete_list = FALSE;
2952    }
2953
2954    BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X", p_results->eir_complete_list);
2955
2956    if( p_uuid_data )
2957    {
2958        for( yy = 0; yy < num_uuid; yy++ )
2959        {
2960            STREAM_TO_UINT16(uuid16, p_uuid_data);
2961            BTM_AddEirService( p_results->eir_uuid, uuid16 );
2962        }
2963    }
2964
2965    p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
2966    if( p_uuid_data )
2967    {
2968        for( yy = 0; yy < num_uuid; yy++ )
2969        {
2970            uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
2971            p_uuid_data += LEN_UUID_32;
2972            if( uuid16 )
2973                BTM_AddEirService( p_results->eir_uuid, uuid16 );
2974        }
2975    }
2976
2977    p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
2978    if( p_uuid_data )
2979    {
2980        for( yy = 0; yy < num_uuid; yy++ )
2981        {
2982            uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
2983            p_uuid_data += LEN_UUID_128;
2984            if( uuid16 )
2985                BTM_AddEirService( p_results->eir_uuid, uuid16 );
2986        }
2987    }
2988}
2989