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