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