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