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