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