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