1 /******************************************************************************
2 *
3 * Copyright (C) 1999-2014 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains functions that handle inquiries. These include
22 * setting discoverable mode, controlling the mode of the Baseband, and
23 * maintaining a small database of inquiry responses, with API for people
24 * to browse it.
25 *
26 ******************************************************************************/
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <stddef.h>
32
33 #include "bt_types.h"
34 #include "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 /********************************************************************************/
50 static const LAP general_inq_lap = {0x9e,0x8b,0x33};
51 static 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
55 const 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 /*
129 If customized UUID look-up table needs to be used,
130 the followings should be defined in bdroid_buildcfg.h.
131 BTM_EIR_UUID_LKUP_TBL = <customized UUID list>
132 BTM_EIR_MAX_SERVICES = <number of UUID in list>
133 */
134 #if (BTM_EIR_MAX_SERVICES == 0)
135 const UINT16 BTM_EIR_UUID_LKUP_TBL[];
136 #else
137 extern 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 /********************************************************************************/
145 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq);
146 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type, tBTM_INQ_FILT_COND *p_filt_cond);
147 static void btm_clr_inq_result_flt (void);
148
149 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
150 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 );
151 #endif
152 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
153 static void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results );
154 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
155 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type );
156 static 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 *******************************************************************************/
BTM_SetDiscoverability(UINT16 inq_mode,UINT16 window,UINT16 interval)175 tBTM_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_API ("BTM_SetDiscoverability");
187 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
188 if (HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
189 {
190 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_DISCOVERABLE_MASK);
195 }
196 }
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_API ("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 *******************************************************************************/
BTM_SetInquiryScanType(UINT16 scan_type)311 tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type)
312 {
313
314 BTM_TRACE_API ("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 */
319 if (!HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
320 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 *******************************************************************************/
BTM_SetPageScanType(UINT16 scan_type)349 tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type)
350 {
351 BTM_TRACE_API ("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 */
356 if (!HCI_LMP_INTERLACED_PAGE_SCAN_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
357 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 *******************************************************************************/
BTM_SetInquiryMode(UINT8 mode)390 tBTM_STATUS BTM_SetInquiryMode (UINT8 mode)
391 {
392 BTM_TRACE_API ("BTM_SetInquiryMode");
393 if (mode == BTM_INQ_RESULT_STANDARD)
394 {
395 /* mandatory mode */
396 }
397 else if (mode == BTM_INQ_RESULT_WITH_RSSI)
398 {
399 if (!HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
400 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 {
405 if (!HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
406 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 *******************************************************************************/
BTM_ReadDiscoverability(UINT16 * p_window,UINT16 * p_interval)435 UINT16 BTM_ReadDiscoverability (UINT16 *p_window, UINT16 *p_interval)
436 {
437 BTM_TRACE_API ("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 *******************************************************************************/
BTM_SetPeriodicInquiryMode(tBTM_INQ_PARMS * p_inqparms,UINT16 max_delay,UINT16 min_delay,tBTM_INQ_RESULTS_CB * p_results_cb)477 tBTM_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_API ("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 ||
508 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*/
511 {
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_WARNING("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 *******************************************************************************/
BTM_CancelPeriodicInquiry(void)572 tBTM_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_API ("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 *******************************************************************************/
BTM_SetConnectability(UINT16 page_mode,UINT16 window,UINT16 interval)617 tBTM_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_API ("BTM_SetConnectability");
623
624 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
625 if (HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
626 {
627 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);
633 }
634 page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
635 #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_API ("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 *******************************************************************************/
BTM_ReadConnectability(UINT16 * p_window,UINT16 * p_interval)709 UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval)
710 {
711 BTM_TRACE_API ("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 *******************************************************************************/
BTM_IsInquiryActive(void)735 UINT16 BTM_IsInquiryActive (void)
736 {
737 BTM_TRACE_API ("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 *******************************************************************************/
BTM_CancelInquiry(void)755 tBTM_STATUS BTM_CancelInquiry(void)
756 {
757 tBTM_STATUS status = BTM_SUCCESS;
758 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
759 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
760 UINT8 active_mode=p_inq->inq_active;
761 #endif
762 BTM_TRACE_API ("BTM_CancelInquiry called");
763
764 /*** Make sure the device is ready ***/
765 if (!BTM_IsDeviceUp())
766 return (BTM_WRONG_MODE);
767
768 /* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
769 if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
770 (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
771 {
772 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
773 p_inq->state = BTM_INQ_INACTIVE_STATE;
774 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; /* Do not notify caller anymore */
775 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL; /* Do not notify caller anymore */
776
777 /* If the event filter is in progress, mark it so that the processing of the return
778 event will be ignored */
779 if (p_inq->inqfilt_active)
780 {
781 p_inq->inqfilt_active = FALSE;
782 p_inq->pending_filt_complete_event++;
783 }
784 /* Initiate the cancel inquiry */
785 else
786 {
787 if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
788 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
789 &&(active_mode & BTM_BR_INQUIRY_MASK)
790 #endif
791 )
792 {
793 if (!btsnd_hcic_inq_cancel())
794 status = BTM_NO_RESOURCES;
795 }
796 #if BLE_INCLUDED == TRUE
797 if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
798 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
799 &&(active_mode & BTM_BLE_INQ_ACTIVE_MASK)
800 #endif
801 )
802 btm_ble_stop_inquiry();
803 #endif
804 }
805
806 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
807 /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event
808 * and then send the BUSY_LEVEL event
809 * btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
810 */
811 #endif
812
813 p_inq->inq_counter++;
814 btm_clr_inq_result_flt();
815 }
816
817 return (status);
818 }
819
820
821 /*******************************************************************************
822 **
823 ** Function BTM_StartInquiry
824 **
825 ** Description This function is called to start an inquiry.
826 **
827 ** Parameters: p_inqparms - pointer to the inquiry information
828 ** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
829 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
830 ** max_resps - maximum amount of devices to search for before ending the inquiry
831 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
832 ** BTM_FILTER_COND_BD_ADDR
833 ** filter_cond - value for the filter (based on filter_cond_type)
834 **
835 ** p_results_cb - Pointer to the callback routine which gets called
836 ** upon receipt of an inquiry result. If this field is
837 ** NULL, the application is not notified.
838 **
839 ** p_cmpl_cb - Pointer to the callback routine which gets called
840 ** upon completion. If this field is NULL, the
841 ** application is not notified when completed.
842 ** Returns tBTM_STATUS
843 ** BTM_CMD_STARTED if successfully initiated
844 ** BTM_BUSY if already in progress
845 ** BTM_ILLEGAL_VALUE if parameter(s) are out of range
846 ** BTM_NO_RESOURCES if could not allocate resources to start the command
847 ** BTM_WRONG_MODE if the device is not up.
848 **
849 *******************************************************************************/
BTM_StartInquiry(tBTM_INQ_PARMS * p_inqparms,tBTM_INQ_RESULTS_CB * p_results_cb,tBTM_CMPL_CB * p_cmpl_cb)850 tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
851 tBTM_CMPL_CB *p_cmpl_cb)
852 {
853 tBTM_STATUS status = BTM_CMD_STARTED;
854 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
855
856 BTM_TRACE_API ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
857 p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
858 p_inqparms->filter_cond_type);
859
860 /* Only one active inquiry is allowed in this implementation.
861 Also do not allow an inquiry if the inquiry filter is being updated */
862 if (p_inq->inq_active || p_inq->inqfilt_active)
863 {
864 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
865 /*check if LE observe is already running*/
866 if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL)
867 {
868 BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
869 p_inq->scan_type = INQ_GENERAL;
870 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
871 btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
872 btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
873 }
874 else
875 #endif
876 {
877 return (BTM_BUSY);
878 BTM_TRACE_API("BTM_StartInquiry: return BUSY");
879 }
880 }
881 else
882 p_inq->scan_type = INQ_GENERAL;
883
884 /*** Make sure the device is ready ***/
885 if (!BTM_IsDeviceUp())
886 return (BTM_WRONG_MODE);
887
888 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
889 (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
890 #if (BLE_INCLUDED == TRUE)
891 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
892 && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
893 #endif
894 )
895 return (BTM_ILLEGAL_VALUE);
896
897 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
898 if(p_inq->next_state==BTM_FINISH)
899 return BTM_ILLEGAL_VALUE;
900 #endif
901
902
903 /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
904 p_inq->inqparms = *p_inqparms;
905
906 /* Initialize the inquiry variables */
907 p_inq->state = BTM_INQ_ACTIVE_STATE;
908 p_inq->p_inq_cmpl_cb = p_cmpl_cb;
909 p_inq->p_inq_results_cb = p_results_cb;
910 p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
911 p_inq->inq_active = p_inqparms->mode;
912
913 BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
914
915 /* interleave scan minimal conditions */
916 #if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE))
917
918 /* check if both modes are present */
919 if((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) && (p_inqparms->mode & BTM_BR_INQUIRY_MASK))
920 {
921 BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
922 p_inqparms->duration=p_inqparms->intl_duration[p_inq->next_state];
923 p_inq->inqparms.duration=p_inqparms->duration;
924 }
925 else
926 {
927 BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x", p_inqparms->mode);
928 p_inq->next_state=BTM_NO_INTERLEAVING;
929 }
930 #endif
931
932
933
934 /* start LE inquiry here if requested */
935 #if BLE_INCLUDED == TRUE
936 if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
937 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
938 &&(p_inq->next_state==BTM_BLE_ONE || p_inq->next_state==BTM_BLE_TWO ||
939 p_inq->next_state==BTM_NO_INTERLEAVING)
940 #endif
941 )
942
943 {
944 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
945 p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
946 BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
947 p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
948 #endif
949 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
950 {
951 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
952 status = BTM_ILLEGAL_VALUE;
953 }
954 /* BLE for now does not support filter condition for inquiry */
955 else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
956 p_inqparms->duration)) != BTM_CMD_STARTED)
957 {
958 BTM_TRACE_ERROR("Err Starting LE Inquiry.");
959 p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
960 }
961 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
962 p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
963 #endif
964
965 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
966 if(p_inq->next_state==BTM_NO_INTERLEAVING)
967 {
968 p_inq->next_state=BTM_FINISH;
969 }
970 else
971 {
972 BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d",
973 p_inq->next_state+1);
974 p_inq->next_state+=1;
975 }
976 /* reset next_state if status <> BTM_Started */
977 if(status!=BTM_CMD_STARTED)
978 p_inq->next_state=BTM_BR_ONE;
979
980 /* if interleave scan..return here */
981 return status;
982 #endif
983
984
985 BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
986 }
987 #endif /* end of BLE_INCLUDED */
988
989 /* we're done with this routine if BR/EDR inquiry is not desired. */
990 if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
991 return status;
992
993 /* BR/EDR inquiry portion */
994 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
995 if((p_inq->next_state==BTM_BR_ONE || p_inq->next_state==BTM_BR_TWO ||
996 p_inq->next_state==BTM_NO_INTERLEAVING ))
997 {
998 p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
999 #endif
1000 #if (defined(BTM_BYPASS_EVENT_FILTERING) && BTM_BYPASS_EVENT_FILTERING == TRUE)
1001 BTM_TRACE_WARNING("BTM: Bypassing event filtering...");
1002 p_inq->inqfilt_active = FALSE;
1003 btm_initiate_inquiry (p_inq);
1004 status = BTM_CMD_STARTED;
1005 #else
1006 /* If a filter is specified, then save it for later and clear the current filter.
1007 The setting of the filter is done upon completion of clearing of the previous
1008 filter.
1009 */
1010 switch (p_inqparms->filter_cond_type)
1011 {
1012 case BTM_CLR_INQUIRY_FILTER:
1013 p_inq->state = BTM_INQ_SET_FILT_STATE;
1014 break;
1015
1016 case BTM_FILTER_COND_DEVICE_CLASS:
1017 case BTM_FILTER_COND_BD_ADDR:
1018 /* The filter is not being used so simply clear it;
1019 the inquiry can start after this operation */
1020 p_inq->state = BTM_INQ_CLR_FILT_STATE;
1021 p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
1022 /* =============>>>> adding LE filtering here ????? */
1023 break;
1024
1025 default:
1026 return (BTM_ILLEGAL_VALUE);
1027 }
1028
1029 /* Before beginning the inquiry the current filter must be cleared, so initiate the command */
1030 if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
1031 &p_inqparms->filter_cond)) != BTM_CMD_STARTED)
1032 p_inq->state = BTM_INQ_INACTIVE_STATE;
1033 #endif
1034
1035 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
1036 if (p_inq->next_state==BTM_NO_INTERLEAVING)
1037 p_inq->next_state=BTM_FINISH;
1038 else
1039 {
1040 BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
1041 p_inq->next_state+1);
1042 p_inq->next_state+=1;
1043 }
1044 }
1045 if (status!=BTM_CMD_STARTED)
1046 {
1047 /* Some error beginning the scan process.
1048 Reset the next_state parameter.. Do we need to reset the inq_active also?
1049 */
1050 BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x", status);
1051 p_inq->next_state=BTM_BR_ONE;
1052 }
1053 #endif
1054
1055
1056 return (status);
1057 }
1058
1059
1060 /*******************************************************************************
1061 **
1062 ** Function BTM_ReadRemoteDeviceName
1063 **
1064 ** Description This function initiates a remote device HCI command to the
1065 ** controller and calls the callback when the process has completed.
1066 **
1067 ** Input Params: remote_bda - device address of name to retrieve
1068 ** p_cb - callback function called when BTM_CMD_STARTED
1069 ** is returned.
1070 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
1071 ** callback.
1072 **
1073 ** Returns
1074 ** BTM_CMD_STARTED is returned if the request was successfully sent
1075 ** to HCI.
1076 ** BTM_BUSY if already in progress
1077 ** BTM_UNKNOWN_ADDR if device address is bad
1078 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1079 ** BTM_WRONG_MODE if the device is not up.
1080 **
1081 *******************************************************************************/
BTM_ReadRemoteDeviceName(BD_ADDR remote_bda,tBTM_CMPL_CB * p_cb,tBT_TRANSPORT transport)1082 tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
1083 ,tBT_TRANSPORT transport)
1084 {
1085 tBTM_INQ_INFO *p_cur = NULL;
1086 tINQ_DB_ENT *p_i;
1087
1088 BTM_TRACE_API ("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]",
1089 remote_bda[0], remote_bda[1], remote_bda[2],
1090 remote_bda[3], remote_bda[4], remote_bda[5]);
1091
1092 /* Use the remote device's clock offset if it is in the local inquiry database */
1093 if ((p_i = btm_inq_db_find (remote_bda)) != NULL)
1094 {
1095 p_cur = &p_i->inq_info;
1096
1097 #if (BTM_INQ_GET_REMOTE_NAME == TRUE)
1098 p_cur->remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
1099 #endif
1100 }
1101 BTM_TRACE_API ("no device found in inquiry db");
1102
1103 #if (BLE_INCLUDED == TRUE)
1104 if (transport == BT_TRANSPORT_LE)
1105 {
1106 return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
1107 }
1108 else
1109 #endif
1110
1111 return (btm_initiate_rem_name (remote_bda, p_cur, BTM_RMT_NAME_EXT,
1112 BTM_EXT_RMT_NAME_TIMEOUT, p_cb));
1113 }
1114
1115 /*******************************************************************************
1116 **
1117 ** Function BTM_CancelRemoteDeviceName
1118 **
1119 ** Description This function initiates the cancel request for the specified
1120 ** remote device.
1121 **
1122 ** Input Params: None
1123 **
1124 ** Returns
1125 ** BTM_CMD_STARTED is returned if the request was successfully sent
1126 ** to HCI.
1127 ** BTM_NO_RESOURCES if could not allocate resources to start the command
1128 ** BTM_WRONG_MODE if there is not an active remote name request.
1129 **
1130 *******************************************************************************/
BTM_CancelRemoteDeviceName(void)1131 tBTM_STATUS BTM_CancelRemoteDeviceName (void)
1132 {
1133 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1134
1135 BTM_TRACE_API ("BTM_CancelRemoteDeviceName()");
1136
1137 /* Make sure there is not already one in progress */
1138 if (p_inq->remname_active)
1139 {
1140 #if BLE_INCLUDED == TRUE
1141 if (BTM_UseLeLink(p_inq->remname_bda))
1142 {
1143 if (btm_ble_cancel_remote_name(p_inq->remname_bda))
1144 return (BTM_CMD_STARTED);
1145 else
1146 return (BTM_UNKNOWN_ADDR);
1147 }
1148 else
1149 #endif
1150 if (btsnd_hcic_rmt_name_req_cancel (p_inq->remname_bda))
1151 return (BTM_CMD_STARTED);
1152 else
1153 return (BTM_NO_RESOURCES);
1154 }
1155 else
1156 return (BTM_WRONG_MODE);
1157 }
1158
1159 /*******************************************************************************
1160 **
1161 ** Function BTM_InqFirstResult
1162 **
1163 ** Description This function looks through the inquiry database for the first
1164 ** used entrysince the LAST inquiry. This is used in conjunction
1165 ** with BTM_InqNext by applications as a way to walk through the
1166 ** inquiry results database.
1167 **
1168 ** Returns pointer to first in-use entry, or NULL if DB is empty
1169 **
1170 *******************************************************************************/
BTM_InqFirstResult(void)1171 tBTM_INQ_INFO *BTM_InqFirstResult (void)
1172 {
1173 UINT16 xx;
1174 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1175 UINT32 cur_inq_count = btm_cb.btm_inq_vars.inq_counter - 1;
1176
1177 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1178 {
1179 if (p_ent->in_use && p_ent->inq_count == cur_inq_count)
1180 return (&p_ent->inq_info);
1181 }
1182
1183 /* If here, no used entry found */
1184 return ((tBTM_INQ_INFO *)NULL);
1185 }
1186
1187
1188 /*******************************************************************************
1189 **
1190 ** Function BTM_InqNextResult
1191 **
1192 ** Description This function looks through the inquiry database for the next
1193 ** used entrysince the LAST inquiry. If the input parameter is NULL,
1194 ** the first entry is returned.
1195 **
1196 ** Returns pointer to next in-use entry, or NULL if no more found.
1197 **
1198 *******************************************************************************/
BTM_InqNextResult(tBTM_INQ_INFO * p_cur)1199 tBTM_INQ_INFO *BTM_InqNextResult (tBTM_INQ_INFO *p_cur)
1200 {
1201 tINQ_DB_ENT *p_ent;
1202 UINT16 inx;
1203 UINT32 cur_inq_count = btm_cb.btm_inq_vars.inq_counter - 1;
1204
1205 if (p_cur)
1206 {
1207 p_ent = (tINQ_DB_ENT *) ((UINT8 *)p_cur - offsetof (tINQ_DB_ENT, inq_info));
1208 inx = (UINT16)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1209
1210 for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++)
1211 {
1212 if (p_ent->in_use && p_ent->inq_count == cur_inq_count)
1213 return (&p_ent->inq_info);
1214 }
1215
1216 /* If here, more entries found */
1217 return ((tBTM_INQ_INFO *)NULL);
1218 }
1219 else
1220 return (BTM_InqDbFirst());
1221 }
1222
1223
1224 /*******************************************************************************
1225 **
1226 ** Function BTM_InqDbRead
1227 **
1228 ** Description This function looks through the inquiry database for a match
1229 ** based on Bluetooth Device Address. This is the application's
1230 ** interface to get the inquiry details of a specific BD address.
1231 **
1232 ** Returns pointer to entry, or NULL if not found
1233 **
1234 *******************************************************************************/
BTM_InqDbRead(BD_ADDR p_bda)1235 tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
1236 {
1237 UINT16 xx;
1238 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1239
1240 BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]",
1241 p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
1242
1243 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1244 {
1245 if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1246 return (&p_ent->inq_info);
1247 }
1248
1249 /* If here, not found */
1250 return ((tBTM_INQ_INFO *)NULL);
1251 }
1252
1253
1254 /*******************************************************************************
1255 **
1256 ** Function BTM_InqDbFirst
1257 **
1258 ** Description This function looks through the inquiry database for the first
1259 ** used entry, and returns that. This is used in conjunction with
1260 ** BTM_InqDbNext by applications as a way to walk through the
1261 ** inquiry database.
1262 **
1263 ** Returns pointer to first in-use entry, or NULL if DB is empty
1264 **
1265 *******************************************************************************/
BTM_InqDbFirst(void)1266 tBTM_INQ_INFO *BTM_InqDbFirst (void)
1267 {
1268 UINT16 xx;
1269 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1270
1271 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1272 {
1273 if (p_ent->in_use)
1274 return (&p_ent->inq_info);
1275 }
1276
1277 /* If here, no used entry found */
1278 return ((tBTM_INQ_INFO *)NULL);
1279 }
1280
1281
1282 /*******************************************************************************
1283 **
1284 ** Function BTM_InqDbNext
1285 **
1286 ** Description This function looks through the inquiry database for the next
1287 ** used entry, and returns that. If the input parameter is NULL,
1288 ** the first entry is returned.
1289 **
1290 ** Returns pointer to next in-use entry, or NULL if no more found.
1291 **
1292 *******************************************************************************/
BTM_InqDbNext(tBTM_INQ_INFO * p_cur)1293 tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur)
1294 {
1295 tINQ_DB_ENT *p_ent;
1296 UINT16 inx;
1297
1298 if (p_cur)
1299 {
1300 p_ent = (tINQ_DB_ENT *) ((UINT8 *)p_cur - offsetof (tINQ_DB_ENT, inq_info));
1301 inx = (UINT16)((p_ent - btm_cb.btm_inq_vars.inq_db) + 1);
1302
1303 for (p_ent = &btm_cb.btm_inq_vars.inq_db[inx]; inx < BTM_INQ_DB_SIZE; inx++, p_ent++)
1304 {
1305 if (p_ent->in_use)
1306 return (&p_ent->inq_info);
1307 }
1308
1309 /* If here, more entries found */
1310 return ((tBTM_INQ_INFO *)NULL);
1311 }
1312 else
1313 return (BTM_InqDbFirst());
1314 }
1315
1316
1317 /*******************************************************************************
1318 **
1319 ** Function BTM_ClearInqDb
1320 **
1321 ** Description This function is called to clear out a device or all devices
1322 ** from the inquiry database.
1323 **
1324 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1325 ** (NULL clears all entries)
1326 **
1327 ** Returns BTM_BUSY if an inquiry, get remote name, or event filter
1328 ** is active, otherwise BTM_SUCCESS
1329 **
1330 *******************************************************************************/
BTM_ClearInqDb(BD_ADDR p_bda)1331 tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda)
1332 {
1333 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1334
1335 /* If an inquiry or remote name is in progress return busy */
1336 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE ||
1337 p_inq->inqfilt_active)
1338 return (BTM_BUSY);
1339
1340 btm_clr_inq_db(p_bda);
1341
1342 return (BTM_SUCCESS);
1343 }
1344
1345
1346 /*******************************************************************************
1347 **
1348 ** Function BTM_ReadNumInqDbEntries
1349 **
1350 ** Returns This function returns the number of entries in the inquiry database.
1351 **
1352 *******************************************************************************/
BTM_ReadNumInqDbEntries(void)1353 UINT8 BTM_ReadNumInqDbEntries (void)
1354 {
1355 UINT8 num_entries;
1356 UINT8 num_results;
1357 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1358
1359 for (num_entries = 0, num_results = 0; num_entries < BTM_INQ_DB_SIZE; num_entries++, p_ent++)
1360 {
1361 if (p_ent->in_use)
1362 num_results++;
1363 }
1364
1365 return (num_results);
1366 }
1367
1368
1369 /*******************************************************************************
1370 **
1371 ** Function BTM_InquiryRegisterForChanges
1372 **
1373 ** Returns This function is called to register a callback for when the
1374 ** inquiry database changes, i.e. new entry or entry deleted.
1375 **
1376 *******************************************************************************/
BTM_InquiryRegisterForChanges(tBTM_INQ_DB_CHANGE_CB * p_cb)1377 tBTM_STATUS BTM_InquiryRegisterForChanges (tBTM_INQ_DB_CHANGE_CB *p_cb)
1378 {
1379 if (!p_cb)
1380 btm_cb.btm_inq_vars.p_inq_change_cb = NULL;
1381 else if (btm_cb.btm_inq_vars.p_inq_change_cb)
1382 return (BTM_BUSY);
1383 else
1384 btm_cb.btm_inq_vars.p_inq_change_cb = p_cb;
1385
1386 return (BTM_SUCCESS);
1387 }
1388
1389
1390 /*******************************************************************************
1391 **
1392 ** Function BTM_SetInquiryFilterCallback
1393 **
1394 ** Description Host can register to be asked whenever an inquiry result
1395 ** is received. If host does not like the device no name
1396 ** request is issued for the device
1397 **
1398 ** Returns void
1399 **
1400 *******************************************************************************/
BTM_SetInquiryFilterCallback(tBTM_FILTER_CB * p_callback)1401 void BTM_SetInquiryFilterCallback (tBTM_FILTER_CB *p_callback)
1402 {
1403 btm_cb.p_inq_filter_cb = p_callback;
1404 }
1405
1406 /*******************************************************************************
1407 **
1408 ** Function BTM_ReadInquiryRspTxPower
1409 **
1410 ** Description This command will read the inquiry Transmit Power level used
1411 ** to transmit the FHS and EIR data packets.
1412 ** This can be used directly in the Tx Power Level EIR data type.
1413 **
1414 ** Returns BTM_SUCCESS if successful
1415 **
1416 *******************************************************************************/
BTM_ReadInquiryRspTxPower(tBTM_CMPL_CB * p_cb)1417 tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb)
1418 {
1419 if (btm_cb.devcb.p_txpwer_cmpl_cb)
1420 return (BTM_BUSY);
1421
1422 btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT );
1423
1424
1425 btm_cb.devcb.p_txpwer_cmpl_cb = p_cb;
1426
1427 if (!btsnd_hcic_read_inq_tx_power ())
1428 {
1429 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
1430 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
1431 return (BTM_NO_RESOURCES);
1432 }
1433 else
1434 return (BTM_CMD_STARTED);
1435 }
1436 /*******************************************************************************
1437 **
1438 ** Function BTM_WriteInquiryTxPower
1439 **
1440 ** Description This command is used to write the inquiry transmit power level
1441 ** used to transmit the inquiry (ID) data packets. The Controller
1442 ** should use the supported TX power level closest to the Tx_Power
1443 ** parameter.
1444 **
1445 ** Returns BTM_SUCCESS if successful
1446 **
1447 *******************************************************************************/
BTM_WriteInquiryTxPower(INT8 tx_power)1448 tBTM_STATUS BTM_WriteInquiryTxPower (INT8 tx_power)
1449 {
1450 tBTM_STATUS status = BTM_SUCCESS;
1451
1452 if (tx_power < BTM_MIN_INQ_TX_POWER || tx_power > BTM_MAX_INQ_TX_POWER)
1453 {
1454 status = BTM_ILLEGAL_VALUE;
1455 }
1456 else if (!btsnd_hcic_write_inq_tx_power(tx_power))
1457 status = BTM_NO_RESOURCES;
1458
1459 return status;
1460 }
1461 /*********************************************************************************
1462 **********************************************************************************
1463 ** **
1464 ** BTM Internal Inquiry Functions **
1465 ** **
1466 **********************************************************************************
1467 *********************************************************************************/
1468 /*******************************************************************************
1469 **
1470 ** Function btm_inq_db_reset
1471 **
1472 ** Description This function is called at at reset to clear the inquiry
1473 ** database & pending callback.
1474 **
1475 ** Returns void
1476 **
1477 *******************************************************************************/
btm_inq_db_reset(void)1478 void btm_inq_db_reset (void)
1479 {
1480 tBTM_REMOTE_DEV_NAME rem_name;
1481 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1482 UINT8 num_responses;
1483 UINT8 temp_inq_active;
1484 tBTM_STATUS status;
1485
1486 btu_stop_timer (&p_inq->inq_timer_ent);
1487
1488 /* If an inquiry or periodic inquiry is active, reset the mode to inactive */
1489 if (p_inq->inq_active != BTM_INQUIRY_INACTIVE)
1490 {
1491 temp_inq_active = p_inq->inq_active; /* Save so state can change BEFORE
1492 callback is called */
1493 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1494
1495 /* If not a periodic inquiry, the complete callback must be called to notify caller */
1496 if (temp_inq_active == BTM_LIMITED_INQUIRY_ACTIVE ||
1497 temp_inq_active == BTM_GENERAL_INQUIRY_ACTIVE)
1498 {
1499 if (p_inq->p_inq_cmpl_cb)
1500 {
1501 num_responses = 0;
1502 (*p_inq->p_inq_cmpl_cb)(&num_responses);
1503 }
1504 }
1505 }
1506
1507 /* Cancel a remote name request if active, and notify the caller (if waiting) */
1508 if (p_inq->remname_active )
1509 {
1510 btu_stop_timer (&p_inq->rmt_name_timer_ent);
1511 p_inq->remname_active = FALSE;
1512 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
1513
1514 if (p_inq->p_remname_cmpl_cb)
1515 {
1516 rem_name.status = BTM_DEV_RESET;
1517
1518 (*p_inq->p_remname_cmpl_cb)(&rem_name);
1519 p_inq->p_remname_cmpl_cb = NULL;
1520 }
1521 }
1522
1523 /* Cancel an inquiry filter request if active, and notify the caller (if waiting) */
1524 if (p_inq->inqfilt_active)
1525 {
1526 p_inq->inqfilt_active = FALSE;
1527
1528 if (p_inq->p_inqfilter_cmpl_cb)
1529 {
1530 status = BTM_DEV_RESET;
1531 (*p_inq->p_inqfilter_cmpl_cb)(&status);
1532 }
1533 }
1534
1535 p_inq->state = BTM_INQ_INACTIVE_STATE;
1536 p_inq->pending_filt_complete_event = 0;
1537 p_inq->p_inq_results_cb = NULL;
1538 btm_clr_inq_db(NULL); /* Clear out all the entries in the database */
1539 btm_clr_inq_result_flt();
1540
1541 p_inq->discoverable_mode = BTM_NON_DISCOVERABLE;
1542 p_inq->connectable_mode = BTM_NON_CONNECTABLE;
1543 p_inq->page_scan_type = BTM_SCAN_TYPE_STANDARD;
1544 p_inq->inq_scan_type = BTM_SCAN_TYPE_STANDARD;
1545
1546 #if BLE_INCLUDED == TRUE
1547 p_inq->discoverable_mode |= BTM_BLE_NON_DISCOVERABLE;
1548 p_inq->connectable_mode |= BTM_BLE_NON_CONNECTABLE;
1549 #endif
1550 return;
1551 }
1552
1553
1554 /*********************************************************************************
1555 **
1556 ** Function btm_inq_db_init
1557 **
1558 ** Description This function is called at startup to initialize the inquiry
1559 ** database.
1560 **
1561 ** Returns void
1562 **
1563 *******************************************************************************/
btm_inq_db_init(void)1564 void btm_inq_db_init (void)
1565 {
1566 #if 0 /* cleared in btm_init; put back in if called from anywhere else! */
1567 memset (&btm_cb.btm_inq_vars, 0, sizeof (tBTM_INQUIRY_VAR_ST));
1568 #endif
1569 btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
1570 }
1571
1572 /*********************************************************************************
1573 **
1574 ** Function btm_inq_stop_on_ssp
1575 **
1576 ** Description This function is called on incoming SSP
1577 **
1578 ** Returns void
1579 **
1580 *******************************************************************************/
btm_inq_stop_on_ssp(void)1581 void btm_inq_stop_on_ssp(void)
1582 {
1583 UINT8 normal_active = (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE);
1584
1585 #if (BTM_INQ_DEBUG == TRUE)
1586 BTM_TRACE_DEBUG ("btm_inq_stop_on_ssp: no_inc_ssp=%d inq_active:0x%x state:%d inqfilt_active:%d",
1587 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);
1588 #endif
1589 if (btm_cb.btm_inq_vars.no_inc_ssp)
1590 {
1591 if (btm_cb.btm_inq_vars.state == BTM_INQ_ACTIVE_STATE)
1592 {
1593 if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
1594 {
1595 BTM_CancelPeriodicInquiry();
1596 }
1597 else if (btm_cb.btm_inq_vars.inq_active & normal_active)
1598 {
1599 /* can not call BTM_CancelInquiry() here. We need to report inquiry complete evt */
1600 btsnd_hcic_inq_cancel();
1601 }
1602 }
1603 /* do not allow inquiry to start */
1604 btm_cb.btm_inq_vars.inq_active |= BTM_SSP_INQUIRY_ACTIVE;
1605 }
1606 }
1607
1608 /*********************************************************************************
1609 **
1610 ** Function btm_inq_clear_ssp
1611 **
1612 ** Description This function is called when pairing_state becomes idle
1613 **
1614 ** Returns void
1615 **
1616 *******************************************************************************/
btm_inq_clear_ssp(void)1617 void btm_inq_clear_ssp(void)
1618 {
1619 btm_cb.btm_inq_vars.inq_active &= ~BTM_SSP_INQUIRY_ACTIVE;
1620 }
1621
1622 /*********************************************************************************
1623 **
1624 ** Function btm_clr_inq_db
1625 **
1626 ** Description This function is called to clear out a device or all devices
1627 ** from the inquiry database.
1628 **
1629 ** Parameter p_bda - (input) BD_ADDR -> Address of device to clear
1630 ** (NULL clears all entries)
1631 **
1632 ** Returns void
1633 **
1634 *******************************************************************************/
btm_clr_inq_db(BD_ADDR p_bda)1635 void btm_clr_inq_db (BD_ADDR p_bda)
1636 {
1637 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1638 tINQ_DB_ENT *p_ent = p_inq->inq_db;
1639 UINT16 xx;
1640
1641 #if (BTM_INQ_DEBUG == TRUE)
1642 BTM_TRACE_DEBUG ("btm_clr_inq_db: inq_active:0x%x state:%d",
1643 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1644 #endif
1645 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1646 {
1647 if (p_ent->in_use)
1648 {
1649 /* If this is the specified BD_ADDR or clearing all devices */
1650 if (p_bda == NULL ||
1651 (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1652 {
1653 p_ent->in_use = FALSE;
1654 #if (BTM_INQ_GET_REMOTE_NAME == TRUE)
1655 p_ent->inq_info.remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
1656 #endif
1657
1658 if (btm_cb.btm_inq_vars.p_inq_change_cb)
1659 (*btm_cb.btm_inq_vars.p_inq_change_cb) (&p_ent->inq_info, FALSE);
1660 }
1661 }
1662 }
1663 #if (BTM_INQ_DEBUG == TRUE)
1664 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d",
1665 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
1666 #endif
1667 }
1668
1669
1670 /*******************************************************************************
1671 **
1672 ** Function btm_clr_inq_result_flt
1673 **
1674 ** Description This function looks through the bdaddr database for a match
1675 ** based on Bluetooth Device Address
1676 **
1677 ** Returns TRUE if found, else FALSE (new entry)
1678 **
1679 *******************************************************************************/
btm_clr_inq_result_flt(void)1680 static void btm_clr_inq_result_flt (void)
1681 {
1682 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
1683 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1684
1685 if (p_inq->p_bd_db)
1686 {
1687 GKI_freebuf(p_inq->p_bd_db);
1688 p_inq->p_bd_db = NULL;
1689 }
1690 p_inq->num_bd_entries = 0;
1691 p_inq->max_bd_entries = 0;
1692 #endif
1693 }
1694
1695 /*******************************************************************************
1696 **
1697 ** Function btm_inq_find_bdaddr
1698 **
1699 ** Description This function looks through the bdaddr database for a match
1700 ** based on Bluetooth Device Address
1701 **
1702 ** Returns TRUE if found, else FALSE (new entry)
1703 **
1704 *******************************************************************************/
btm_inq_find_bdaddr(BD_ADDR p_bda)1705 BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda)
1706 {
1707 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
1708 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1709 tINQ_BDADDR *p_db = &p_inq->p_bd_db[0];
1710 UINT16 xx;
1711
1712 /* Don't bother searching, database doesn't exist or periodic mode */
1713 if ((p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) || !p_db)
1714 return (FALSE);
1715
1716 for (xx = 0; xx < p_inq->num_bd_entries; xx++, p_db++)
1717 {
1718 if (!memcmp(p_db->bd_addr, p_bda, BD_ADDR_LEN)
1719 && p_db->inq_count == p_inq->inq_counter)
1720 return (TRUE);
1721 }
1722
1723 if (xx < p_inq->max_bd_entries)
1724 {
1725 p_db->inq_count = p_inq->inq_counter;
1726 memcpy(p_db->bd_addr, p_bda, BD_ADDR_LEN);
1727 p_inq->num_bd_entries++;
1728 }
1729
1730 #endif
1731 /* If here, New Entry */
1732 return (FALSE);
1733 }
1734
1735 /*******************************************************************************
1736 **
1737 ** Function btm_inq_db_find
1738 **
1739 ** Description This function looks through the inquiry database for a match
1740 ** based on Bluetooth Device Address
1741 **
1742 ** Returns pointer to entry, or NULL if not found
1743 **
1744 *******************************************************************************/
btm_inq_db_find(BD_ADDR p_bda)1745 tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
1746 {
1747 UINT16 xx;
1748 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1749
1750 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1751 {
1752 if ((p_ent->in_use) && (!memcmp (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN)))
1753 return (p_ent);
1754 }
1755
1756 /* If here, not found */
1757 return (NULL);
1758 }
1759
1760
1761 /*******************************************************************************
1762 **
1763 ** Function btm_inq_db_new
1764 **
1765 ** Description This function looks through the inquiry database for an unused
1766 ** entry. If no entry is free, it allocates the oldest entry.
1767 **
1768 ** Returns pointer to entry
1769 **
1770 *******************************************************************************/
btm_inq_db_new(BD_ADDR p_bda)1771 tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda)
1772 {
1773 UINT16 xx;
1774 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
1775 tINQ_DB_ENT *p_old = btm_cb.btm_inq_vars.inq_db;
1776 UINT32 ot = 0xFFFFFFFF;
1777
1778 for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
1779 {
1780 if (!p_ent->in_use)
1781 {
1782 memset (p_ent, 0, sizeof (tINQ_DB_ENT));
1783 memcpy (p_ent->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1784 p_ent->in_use = TRUE;
1785
1786 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
1787 p_ent->inq_info.remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
1788 #endif
1789
1790 return (p_ent);
1791 }
1792
1793 if (p_ent->time_of_resp < ot)
1794 {
1795 p_old = p_ent;
1796 ot = p_ent->time_of_resp;
1797 }
1798 }
1799
1800 /* If here, no free entry found. Return the oldest. */
1801
1802 /* Before deleting the oldest, if anyone is registered for change */
1803 /* notifications, then tell him we are deleting an entry. */
1804 if (btm_cb.btm_inq_vars.p_inq_change_cb)
1805 (*btm_cb.btm_inq_vars.p_inq_change_cb) (&p_old->inq_info, FALSE);
1806
1807 memset (p_old, 0, sizeof (tINQ_DB_ENT));
1808 memcpy (p_old->inq_info.results.remote_bd_addr, p_bda, BD_ADDR_LEN);
1809 p_old->in_use = TRUE;
1810
1811 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
1812 p_old->inq_info.remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
1813 #endif
1814
1815 return (p_old);
1816 }
1817
1818
1819 /*******************************************************************************
1820 **
1821 ** Function btm_set_inq_event_filter
1822 **
1823 ** Description This function is called to set the inquiry event filter.
1824 ** It is called by either internally, or by the external API function
1825 ** (BTM_SetInqEventFilter). It is used internally as part of the
1826 ** inquiry processing.
1827 **
1828 ** Input Params:
1829 ** filter_cond_type - this is the type of inquiry filter to apply:
1830 ** BTM_FILTER_COND_DEVICE_CLASS,
1831 ** BTM_FILTER_COND_BD_ADDR, or
1832 ** BTM_CLR_INQUIRY_FILTER
1833 **
1834 ** p_filt_cond - this is either a BD_ADDR or DEV_CLASS depending on the
1835 ** filter_cond_type (See section 4.7.3 of Core Spec 1.0b).
1836 **
1837 ** Returns BTM_CMD_STARTED if successfully initiated
1838 ** BTM_NO_RESOURCES if couldn't get a memory pool buffer
1839 ** BTM_ILLEGAL_VALUE if a bad parameter was detected
1840 **
1841 *******************************************************************************/
btm_set_inq_event_filter(UINT8 filter_cond_type,tBTM_INQ_FILT_COND * p_filt_cond)1842 static tBTM_STATUS btm_set_inq_event_filter (UINT8 filter_cond_type,
1843 tBTM_INQ_FILT_COND *p_filt_cond)
1844 {
1845 UINT8 condition_length = DEV_CLASS_LEN * 2;
1846 UINT8 condition_buf[DEV_CLASS_LEN * 2];
1847 UINT8 *p_cond = condition_buf; /* points to the condition to pass to HCI */
1848
1849 #if (BTM_INQ_DEBUG == TRUE)
1850 BTM_TRACE_DEBUG ("btm_set_inq_event_filter: filter type %d [Clear-0, COD-1, BDADDR-2]",
1851 filter_cond_type);
1852 BTM_TRACE_DEBUG (" condition [%02x%02x%02x %02x%02x%02x]",
1853 p_filt_cond->bdaddr_cond[0], p_filt_cond->bdaddr_cond[1], p_filt_cond->bdaddr_cond[2],
1854 p_filt_cond->bdaddr_cond[3], p_filt_cond->bdaddr_cond[4], p_filt_cond->bdaddr_cond[5]);
1855 #endif
1856
1857 /* Load the correct filter condition to pass to the lower layer */
1858 switch (filter_cond_type)
1859 {
1860 case BTM_FILTER_COND_DEVICE_CLASS:
1861 /* copy the device class and device class fields into contiguous memory to send to HCI */
1862 memcpy (condition_buf, p_filt_cond->cod_cond.dev_class, DEV_CLASS_LEN);
1863 memcpy (&condition_buf[DEV_CLASS_LEN],
1864 p_filt_cond->cod_cond.dev_class_mask, DEV_CLASS_LEN);
1865
1866 /* condition length should already be set as the default */
1867 break;
1868
1869 case BTM_FILTER_COND_BD_ADDR:
1870 p_cond = p_filt_cond->bdaddr_cond;
1871
1872 /* condition length should already be set as the default */
1873 break;
1874
1875 case BTM_CLR_INQUIRY_FILTER:
1876 condition_length = 0;
1877 break;
1878
1879 default:
1880 return (BTM_ILLEGAL_VALUE); /* Bad parameter was passed in */
1881 }
1882
1883 btm_cb.btm_inq_vars.inqfilt_active = TRUE;
1884
1885 /* Filter the inquiry results for the specified condition type and value */
1886 if (btsnd_hcic_set_event_filter(HCI_FILTER_INQUIRY_RESULT, filter_cond_type,
1887 p_cond, condition_length))
1888
1889 return (BTM_CMD_STARTED);
1890 else
1891 return (BTM_NO_RESOURCES);
1892 }
1893
1894
1895 /*******************************************************************************
1896 **
1897 ** Function btm_event_filter_complete
1898 **
1899 ** Description This function is called when a set event filter has completed.
1900 ** Note: This routine currently only handles inquiry filters.
1901 ** Connection filters are ignored for now.
1902 **
1903 ** Returns void
1904 **
1905 *******************************************************************************/
btm_event_filter_complete(UINT8 * p)1906 void btm_event_filter_complete (UINT8 *p)
1907 {
1908 UINT8 hci_status;
1909 tBTM_STATUS status;
1910 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
1911 tBTM_CMPL_CB *p_cb = p_inq->p_inqfilter_cmpl_cb;
1912
1913 #if (BTM_INQ_DEBUG == TRUE)
1914 BTM_TRACE_DEBUG ("btm_event_filter_complete: inq_active:0x%x state:%d inqfilt_active:%d",
1915 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
1916 #endif
1917 /* If the filter complete event is from an old or cancelled request, ignore it */
1918 if(p_inq->pending_filt_complete_event)
1919 {
1920 p_inq->pending_filt_complete_event--;
1921 return;
1922 }
1923
1924 /* Only process the inquiry filter; Ignore the connection filter until it
1925 is used by the upper layers */
1926 if (p_inq->inqfilt_active == TRUE )
1927 {
1928 /* Extract the returned status from the buffer */
1929 STREAM_TO_UINT8 (hci_status, p);
1930 if (hci_status != HCI_SUCCESS)
1931 {
1932 /* If standalone operation, return the error status; if embedded in the inquiry, continue the inquiry */
1933 BTM_TRACE_WARNING ("BTM Warning: Set Event Filter Failed (HCI returned 0x%x)", hci_status);
1934 status = BTM_ERR_PROCESSING;
1935 }
1936 else
1937 status = BTM_SUCCESS;
1938
1939 /* If the set filter was initiated externally (via BTM_SetInqEventFilter), call the
1940 callback function to notify the initiator that it has completed */
1941 if (p_inq->state == BTM_INQ_INACTIVE_STATE)
1942 {
1943 p_inq->inqfilt_active = FALSE;
1944 if (p_cb)
1945 (*p_cb) (&status);
1946 }
1947 else /* An inquiry is active (the set filter command was internally generated),
1948 process the next state of the process (Set a new filter or start the inquiry). */
1949 {
1950 if(status != BTM_SUCCESS)
1951 {
1952 /* Process the inquiry complete (Error Status) */
1953 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1954
1955 /* btm_process_inq_complete() does not restore the following settings on periodic inquiry */
1956 p_inq->inqfilt_active = FALSE;
1957 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
1958 p_inq->state = BTM_INQ_INACTIVE_STATE;
1959
1960 return;
1961 }
1962
1963 /* Check to see if a new filter needs to be set up */
1964 if (p_inq->state == BTM_INQ_CLR_FILT_STATE)
1965 {
1966 if ((status = btm_set_inq_event_filter (p_inq->inqparms.filter_cond_type, &p_inq->inqparms.filter_cond)) == BTM_CMD_STARTED)
1967 {
1968 p_inq->state = BTM_INQ_SET_FILT_STATE;
1969 }
1970 else /* Error setting the filter: Call the initiator's callback function to indicate a failure */
1971 {
1972 p_inq->inqfilt_active = FALSE;
1973
1974 /* Process the inquiry complete (Error Status) */
1975 btm_process_inq_complete (BTM_ERR_PROCESSING, (UINT8)(p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK));
1976 }
1977 }
1978 else /* Initiate the Inquiry or Periodic Inquiry */
1979 {
1980 p_inq->state = BTM_INQ_ACTIVE_STATE;
1981 p_inq->inqfilt_active = FALSE;
1982 btm_initiate_inquiry (p_inq);
1983 }
1984 }
1985 }
1986 }
1987
1988
1989 /*******************************************************************************
1990 **
1991 ** Function btm_initiate_inquiry
1992 **
1993 ** Description This function is called to start an inquiry or periodic inquiry
1994 ** upon completion of the setting and/or clearing of the inquiry filter.
1995 **
1996 ** Inputs: p_inq (btm_cb.btm_inq_vars) - pointer to saved inquiry information
1997 ** mode - GENERAL or LIMITED inquiry
1998 ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
1999 ** max_resps - maximum amount of devices to search for before ending the inquiry
2000 ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
2001 ** BTM_FILTER_COND_BD_ADDR
2002 ** filter_cond - value for the filter (based on filter_cond_type)
2003 **
2004 ** Returns If an error occurs the initiator's callback is called with the error status.
2005 **
2006 *******************************************************************************/
btm_initiate_inquiry(tBTM_INQUIRY_VAR_ST * p_inq)2007 static void btm_initiate_inquiry (tBTM_INQUIRY_VAR_ST *p_inq)
2008 {
2009 const LAP *lap;
2010 tBTM_INQ_PARMS *p_inqparms = &p_inq->inqparms;
2011
2012 #if (BTM_INQ_DEBUG == TRUE)
2013 BTM_TRACE_DEBUG ("btm_initiate_inquiry: inq_active:0x%x state:%d inqfilt_active:%d",
2014 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2015 #endif
2016 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
2017 btm_acl_update_busy_level (BTM_BLI_INQ_EVT);
2018 #endif
2019
2020 if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE)
2021 {
2022 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
2023 return;
2024 }
2025
2026 /* Make sure the number of responses doesn't overflow the database configuration */
2027 p_inqparms->max_resps = (UINT8)((p_inqparms->max_resps <= BTM_INQ_DB_SIZE) ? p_inqparms->max_resps : BTM_INQ_DB_SIZE);
2028
2029 lap = (p_inq->inq_active & BTM_LIMITED_INQUIRY_ACTIVE) ? &limited_inq_lap : &general_inq_lap;
2030
2031 if (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)
2032 {
2033 if (!btsnd_hcic_per_inq_mode (p_inq->per_max_delay,
2034 p_inq->per_min_delay,
2035 *lap, p_inqparms->duration,
2036 p_inqparms->max_resps))
2037 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
2038 }
2039 else
2040 {
2041 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
2042 btm_clr_inq_result_flt();
2043
2044 /* Allocate memory to hold bd_addrs responding */
2045 if ((p_inq->p_bd_db = (tINQ_BDADDR *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
2046 {
2047 p_inq->max_bd_entries = (UINT16)(GKI_MAX_BUF_SIZE / sizeof(tINQ_BDADDR));
2048 memset(p_inq->p_bd_db, 0, GKI_MAX_BUF_SIZE);
2049 /* BTM_TRACE_DEBUG("btm_initiate_inquiry: memory allocated for %d bdaddrs",
2050 p_inq->max_bd_entries); */
2051 }
2052
2053 if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, 0))
2054 #else
2055 if (!btsnd_hcic_inquiry(*lap, p_inqparms->duration, p_inqparms->max_resps))
2056 #endif /* BTM_USE_INQ_RESULTS_FILTER */
2057 btm_process_inq_complete (BTM_NO_RESOURCES, (UINT8)(p_inqparms->mode & BTM_BR_INQUIRY_MASK));
2058 }
2059 }
2060
2061 /*******************************************************************************
2062 **
2063 ** Function btm_process_inq_results
2064 **
2065 ** Description This function is called when inquiry results are received from
2066 ** the device. It updates the inquiry database. If the inquiry
2067 ** database is full, the oldest entry is discarded.
2068 **
2069 ** Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
2070 ** BTM_INQ_RESULT_WITH_RSSI
2071 ** BTM_INQ_RESULT_EXTENDED
2072 **
2073 ** Returns void
2074 **
2075 *******************************************************************************/
btm_process_inq_results(UINT8 * p,UINT8 inq_res_mode)2076 void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
2077 {
2078 UINT8 num_resp, xx;
2079 BD_ADDR bda;
2080 tINQ_DB_ENT *p_i;
2081 tBTM_INQ_RESULTS *p_cur=NULL;
2082 BOOLEAN is_new = TRUE;
2083 BOOLEAN update = FALSE;
2084 INT8 i_rssi;
2085 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2086 tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
2087 UINT8 page_scan_rep_mode = 0;
2088 UINT8 page_scan_per_mode = 0;
2089 UINT8 page_scan_mode = 0;
2090 UINT8 rssi = 0;
2091 DEV_CLASS dc;
2092 UINT16 clock_offset;
2093 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
2094 UINT8 *p_eir_data = NULL;
2095 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2096 UINT8 remote_name_len;
2097 #endif
2098 #endif
2099
2100 #if (BTM_INQ_DEBUG == TRUE)
2101 BTM_TRACE_DEBUG ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
2102 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2103 #endif
2104 /* Only process the results if the BR inquiry is still active */
2105 if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
2106 return;
2107
2108 STREAM_TO_UINT8 (num_resp, p);
2109
2110 for (xx = 0; xx < num_resp; xx++)
2111 {
2112 update = FALSE;
2113 /* Extract inquiry results */
2114 STREAM_TO_BDADDR (bda, p);
2115 STREAM_TO_UINT8 (page_scan_rep_mode, p);
2116 STREAM_TO_UINT8 (page_scan_per_mode, p);
2117
2118 if (inq_res_mode == BTM_INQ_RESULT_STANDARD)
2119 {
2120 STREAM_TO_UINT8(page_scan_mode, p);
2121 }
2122
2123 STREAM_TO_DEVCLASS (dc, p);
2124 STREAM_TO_UINT16 (clock_offset, p);
2125 if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
2126 {
2127 STREAM_TO_UINT8(rssi, p);
2128 }
2129
2130 p_i = btm_inq_db_find (bda);
2131
2132 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
2133 /* Only process the num_resp is smaller than max_resps.
2134 If results are queued to BTU task while canceling inquiry,
2135 or when more than one result is in this response, > max_resp
2136 responses could be processed which can confuse some apps
2137 */
2138 if (p_inq->inqparms.max_resps &&
2139 p_inq->inq_cmpl_info.num_resp >= p_inq->inqparms.max_resps
2140 #if BLE_INCLUDED == TRUE
2141 /* new device response */
2142 && ( p_i == NULL ||
2143 /* exisiting device with BR/EDR info */
2144 (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0)
2145 )
2146 #endif
2147
2148 )
2149 {
2150 /* BTM_TRACE_WARNING("INQ RES: Extra Response Received...ignoring"); */
2151 return;
2152 }
2153 #endif
2154
2155 /* Check if this address has already been processed for this inquiry */
2156 if (btm_inq_find_bdaddr(bda))
2157 {
2158 /* BTM_TRACE_DEBUG("BDA seen before [%02x%02x %02x%02x %02x%02x]",
2159 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);*/
2160 /* By default suppose no update needed */
2161 i_rssi = (INT8)rssi;
2162
2163 /* If this new RSSI is higher than the last one */
2164 if(p_inq->inqparms.report_dup && (rssi != 0) &&
2165 p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0
2166 #if BLE_INCLUDED == TRUE
2167 /* BR/EDR inquiry information update */
2168 || (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0
2169 #endif
2170 ))
2171 {
2172 p_cur = &p_i->inq_info.results;
2173 BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);
2174 p_cur->rssi = i_rssi;
2175 update = TRUE;
2176 }
2177 /* If we received a second Extended Inq Event for an already */
2178 /* discovered device, this is because for the first one EIR was not received */
2179 else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i))
2180 {
2181 p_cur = &p_i->inq_info.results;
2182 update = TRUE;
2183 }
2184 /* If no update needed continue with next response (if any) */
2185 else
2186 continue;
2187 }
2188
2189 /* Host can be registered to verify comming BDA or DC */
2190 if (btm_cb.p_inq_filter_cb)
2191 {
2192 if (!(* btm_cb.p_inq_filter_cb) (bda, dc))
2193 {
2194 continue;
2195 }
2196 }
2197
2198 /* If existing entry, use that, else get a new one (possibly reusing the oldest) */
2199 if (p_i == NULL)
2200 {
2201 p_i = btm_inq_db_new (bda);
2202 is_new = TRUE;
2203 }
2204
2205 /* If an entry for the device already exists, overwrite it ONLY if it is from
2206 a previous inquiry. (Ignore it if it is a duplicate response from the same
2207 inquiry.
2208 */
2209 else if (p_i->inq_count == p_inq->inq_counter
2210 #if (BLE_INCLUDED == TRUE )
2211 && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR)
2212 #endif
2213 )
2214 is_new = FALSE;
2215
2216 /* keep updating RSSI to have latest value */
2217 if( inq_res_mode != BTM_INQ_RESULT_STANDARD )
2218 p_i->inq_info.results.rssi = (INT8)rssi;
2219 else
2220 p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
2221
2222 if (is_new == TRUE)
2223 {
2224 /* Save the info */
2225 p_cur = &p_i->inq_info.results;
2226 p_cur->page_scan_rep_mode = page_scan_rep_mode;
2227 p_cur->page_scan_per_mode = page_scan_per_mode;
2228 p_cur->page_scan_mode = page_scan_mode;
2229 p_cur->dev_class[0] = dc[0];
2230 p_cur->dev_class[1] = dc[1];
2231 p_cur->dev_class[2] = dc[2];
2232 p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
2233
2234 p_i->time_of_resp = GKI_get_tick_count ();
2235
2236 if (p_i->inq_count != p_inq->inq_counter)
2237 p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
2238
2239 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2240 p_cur->inq_result_type = BTM_INQ_RESULT_BR;
2241 if (p_i->inq_count != p_inq->inq_counter)
2242 {
2243 p_cur->device_type = BT_DEVICE_TYPE_BREDR;
2244 p_i->scan_rsp = FALSE;
2245 }
2246 else
2247 p_cur->device_type |= BT_DEVICE_TYPE_BREDR;
2248 #endif
2249 p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */
2250
2251 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
2252 /* If the number of responses found and not unlimited, issue a cancel inquiry */
2253 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) &&
2254 p_inq->inqparms.max_resps &&
2255 p_inq->inq_cmpl_info.num_resp == p_inq->inqparms.max_resps
2256 #if BLE_INCLUDED == TRUE
2257 /* BLE scanning is active and received adv */
2258 && ((((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) &&
2259 p_cur->device_type == BT_DEVICE_TYPE_DUMO && p_i->scan_rsp) ||
2260 (p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) == 0)
2261 #endif
2262 )
2263 {
2264 /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */
2265 btsnd_hcic_inq_cancel();
2266
2267 #if BLE_INCLUDED == TRUE
2268 if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
2269 btm_ble_stop_inquiry();
2270 #endif
2271
2272
2273 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
2274 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2275 #endif
2276 }
2277 #endif
2278 /* Initialize flag to FALSE. This flag is set/used by application */
2279 p_i->inq_info.appl_knows_rem_name = FALSE;
2280 }
2281
2282 if (is_new || update)
2283 {
2284 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2285 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
2286 if( inq_res_mode == BTM_INQ_RESULT_EXTENDED )
2287 {
2288 if((p_eir_data = BTM_CheckEirData( p, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE,
2289 &remote_name_len )) == NULL)
2290 {
2291 p_eir_data = BTM_CheckEirData( p, BTM_EIR_SHORTENED_LOCAL_NAME_TYPE,
2292 &remote_name_len );
2293 }
2294
2295 if( p_eir_data )
2296 {
2297 if( remote_name_len > BTM_MAX_REM_BD_NAME_LEN )
2298 remote_name_len = BTM_MAX_REM_BD_NAME_LEN;
2299
2300 p_i->inq_info.remote_name_len = remote_name_len;
2301 memcpy( p_i->inq_info.remote_name, p_eir_data, p_i->inq_info.remote_name_len );
2302 p_i->inq_info.remote_name[p_i->inq_info.remote_name_len] = 0;
2303 p_i->inq_info.remote_name_state = BTM_INQ_RMT_NAME_DONE;
2304 }
2305 else
2306 p_i->inq_info.remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
2307 }
2308 else
2309 #endif
2310 {
2311 /* Clear out the device name so that it can be re-read */
2312 p_i->inq_info.remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
2313 }
2314 #endif /*(BTM_INQ_GET_REMOTE_NAME==TRUE)*/
2315
2316 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
2317 if( inq_res_mode == BTM_INQ_RESULT_EXTENDED )
2318 {
2319 memset( p_cur->eir_uuid, 0,
2320 BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS/8));
2321 /* set bit map of UUID list from received EIR */
2322 btm_set_eir_uuid( p, p_cur );
2323 p_eir_data = p;
2324 }
2325 else
2326 p_eir_data = NULL;
2327 #endif
2328
2329 /* If a callback is registered, call it with the results */
2330 if (p_inq_results_cb)
2331 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
2332 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);
2333 #else
2334 (p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, NULL);
2335 #endif
2336
2337 /* If anyone is registered for change notifications, then tell him we added an entry. */
2338 if (p_inq->p_inq_change_cb)
2339 (*p_inq->p_inq_change_cb) (&p_i->inq_info, TRUE);
2340 }
2341 }
2342 }
2343
2344 /*******************************************************************************
2345 **
2346 ** Function btm_sort_inq_result
2347 **
2348 ** Description This function is called when inquiry complete is received
2349 ** from the device to sort inquiry results based on rssi.
2350 **
2351 ** Returns void
2352 **
2353 *******************************************************************************/
btm_sort_inq_result(void)2354 void btm_sort_inq_result(void)
2355 {
2356 UINT8 xx, yy, num_resp;
2357 tINQ_DB_ENT *p_tmp = NULL;
2358 tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
2359 tINQ_DB_ENT *p_next = btm_cb.btm_inq_vars.inq_db+1;
2360 int size;
2361
2362 num_resp = (btm_cb.btm_inq_vars.inq_cmpl_info.num_resp<BTM_INQ_DB_SIZE)?
2363 btm_cb.btm_inq_vars.inq_cmpl_info.num_resp: BTM_INQ_DB_SIZE;
2364
2365 if((p_tmp = (tINQ_DB_ENT *)GKI_getbuf(sizeof(tINQ_DB_ENT))) != NULL)
2366 {
2367 size = sizeof(tINQ_DB_ENT);
2368 for(xx = 0; xx < num_resp-1; xx++, p_ent++)
2369 {
2370 for(yy = xx+1, p_next = p_ent+1; yy < num_resp; yy++, p_next++)
2371 {
2372 if(p_ent->inq_info.results.rssi < p_next->inq_info.results.rssi)
2373 {
2374 memcpy (p_tmp, p_next, size);
2375 memcpy (p_next, p_ent, size);
2376 memcpy (p_ent, p_tmp, size);
2377 }
2378 }
2379 }
2380
2381 GKI_freebuf(p_tmp);
2382 }
2383 }
2384
2385 /*******************************************************************************
2386 **
2387 ** Function btm_process_inq_complete
2388 **
2389 ** Description This function is called when inquiry complete is received
2390 ** from the device. Call the callback if not in periodic inquiry
2391 ** mode AND it is not NULL (The caller wants the event).
2392 **
2393 ** The callback pass back the status and the number of responses
2394 **
2395 ** Returns void
2396 **
2397 *******************************************************************************/
btm_process_inq_complete(UINT8 status,UINT8 mode)2398 void btm_process_inq_complete (UINT8 status, UINT8 mode)
2399 {
2400 tBTM_CMPL_CB *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
2401 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2402
2403 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2404 tBTM_INQ_INFO *p_cur;
2405 UINT8 tempstate;
2406 #endif
2407 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2408 /* inquiry inactive case happens when inquiry is cancelled.
2409 Make mode 0 for no further inquiries from the current inquiry process
2410 */
2411 if(status!=HCI_SUCCESS || p_inq->next_state==BTM_FINISH || !p_inq->inq_active)
2412 {
2413 /* re-initialize for next inquiry request */
2414 p_inq->next_state=BTM_BR_ONE;
2415 /* make the mode 0 here */
2416 p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
2417
2418 }
2419 #endif
2420
2421 #if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)
2422 p_inq->inqparms.mode &= ~(mode);
2423 #endif
2424
2425 if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active)
2426 {
2427 /*end of LE observe*/
2428 p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2429 p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2430 p_inq->scan_type=INQ_NONE;
2431 }
2432
2433
2434 #if (BTM_INQ_DEBUG == TRUE)
2435 BTM_TRACE_DEBUG ("btm_process_inq_complete inq_active:0x%x state:%d inqfilt_active:%d",
2436 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2437 #endif
2438 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
2439 btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
2440 #endif
2441 /* Ignore any stray or late complete messages if the inquiry is not active */
2442 if (p_inq->inq_active)
2443 {
2444 p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);
2445
2446 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2447 if (p_inq->inq_cmpl_info.status == BTM_SUCCESS)
2448 {
2449 for (p_cur = BTM_InqDbFirst(); p_cur; p_cur = BTM_InqDbNext (p_cur))
2450 {
2451 if (p_cur->remote_name_state == BTM_INQ_RMT_NAME_EMPTY)
2452 {
2453 tempstate = p_cur->remote_name_state;
2454 p_cur->remote_name_state = BTM_INQ_RMT_NAME_PENDING;
2455
2456 if (btm_initiate_rem_name (p_cur->results.remote_bd_addr,
2457 p_cur, BTM_RMT_NAME_INQ,
2458 BTM_INQ_RMT_NAME_TIMEOUT, NULL) != BTM_CMD_STARTED)
2459 p_cur->remote_name_state = tempstate;
2460 else
2461 return;
2462 }
2463 }
2464 }
2465 #endif
2466
2467 /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
2468 if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)
2469 {
2470 p_inq->state = BTM_INQ_INACTIVE_STATE;
2471
2472 /* Increment so the start of a next inquiry has a new count */
2473 p_inq->inq_counter++;
2474
2475 btm_clr_inq_result_flt();
2476
2477 if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
2478 HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
2479 {
2480 btm_sort_inq_result();
2481 }
2482
2483 /* Clear the results callback if set */
2484 p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
2485 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2486 p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;
2487
2488 /* If we have a callback registered for inquiry complete, call it */
2489 BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d",
2490 p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
2491
2492 if (p_inq_cb)
2493 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2494 }
2495 #if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
2496 if(p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))
2497 {
2498 /* make inquiry inactive for next iteration */
2499 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2500 /* call the inquiry again */
2501 BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
2502 }
2503 #endif
2504 }
2505 if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
2506 {
2507 p_inq->scan_type = INQ_NONE;
2508 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
2509 /* check if the LE observe is pending */
2510 if(p_inq->p_inq_ble_results_cb != NULL)
2511 {
2512 BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");
2513 BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
2514 }
2515 #endif
2516 }
2517 #if (BTM_INQ_DEBUG == TRUE)
2518 BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d",
2519 btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
2520 #endif
2521 }
2522
2523 /*******************************************************************************
2524 **
2525 ** Function btm_process_cancel_complete
2526 **
2527 ** Description This function is called when inquiry cancel complete is received
2528 ** from the device.This function will also call the btm_process_inq_complete
2529 ** This function is needed to differentiate a cancel_cmpl_evt from the
2530 ** inq_cmpl_evt
2531 **
2532 ** Returns void
2533 **
2534 *******************************************************************************/
btm_process_cancel_complete(UINT8 status,UINT8 mode)2535 void btm_process_cancel_complete(UINT8 status, UINT8 mode)
2536 {
2537 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
2538 btm_acl_update_busy_level (BTM_BLI_INQ_CANCEL_EVT);
2539 #endif
2540 btm_process_inq_complete(status, mode);
2541 }
2542 /*******************************************************************************
2543 **
2544 ** Function btm_initiate_rem_name
2545 **
2546 ** Description This function looks initiates a remote name request. It is called
2547 ** either by GAP or by the API call BTM_ReadRemoteDeviceName.
2548 **
2549 ** Input Params: p_cur - pointer to an inquiry result structure (NULL if nonexistent)
2550 ** p_cb - callback function called when BTM_CMD_STARTED
2551 ** is returned.
2552 ** A pointer to tBTM_REMOTE_DEV_NAME is passed to the
2553 ** callback.
2554 **
2555 ** Returns
2556 ** BTM_CMD_STARTED is returned if the request was sent to HCI.
2557 ** BTM_BUSY if already in progress
2558 ** BTM_NO_RESOURCES if could not allocate resources to start the command
2559 ** BTM_WRONG_MODE if the device is not up.
2560 **
2561 *******************************************************************************/
btm_initiate_rem_name(BD_ADDR remote_bda,tBTM_INQ_INFO * p_cur,UINT8 origin,UINT32 timeout,tBTM_CMPL_CB * p_cb)2562 tBTM_STATUS btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
2563 UINT8 origin, UINT32 timeout, tBTM_CMPL_CB *p_cb)
2564 {
2565 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2566 BOOLEAN cmd_ok;
2567
2568
2569 /*** Make sure the device is ready ***/
2570 if (!BTM_IsDeviceUp())
2571 return (BTM_WRONG_MODE);
2572
2573
2574 if (origin == BTM_RMT_NAME_SEC)
2575 {
2576 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2577 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2578 if (cmd_ok)
2579 return BTM_CMD_STARTED;
2580 else
2581 return BTM_NO_RESOURCES;
2582 }
2583 /* Make sure there are no two remote name requests from external API in progress */
2584 else if (origin == BTM_RMT_NAME_EXT)
2585 {
2586 if (p_inq->remname_active)
2587 {
2588 return (BTM_BUSY);
2589 }
2590 else
2591 {
2592 /* If there is no remote name request running,call the callback function and start timer */
2593 p_inq->p_remname_cmpl_cb = p_cb;
2594 memcpy(p_inq->remname_bda, remote_bda, BD_ADDR_LEN);
2595 btu_start_timer (&p_inq->rmt_name_timer_ent,
2596 BTU_TTYPE_BTM_RMT_NAME,
2597 timeout);
2598
2599 /* If the database entry exists for the device, use its clock offset */
2600 if (p_cur)
2601 {
2602 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2603 p_cur->results.page_scan_rep_mode,
2604 p_cur->results.page_scan_mode,
2605 (UINT16)(p_cur->results.clock_offset |
2606 BTM_CLOCK_OFFSET_VALID));
2607 }
2608 else /* Otherwise use defaults and mark the clock offset as invalid */
2609 {
2610 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda, HCI_PAGE_SCAN_REP_MODE_R1,
2611 HCI_MANDATARY_PAGE_SCAN_MODE, 0);
2612 }
2613 if (cmd_ok)
2614 {
2615 p_inq->remname_active = TRUE;
2616 return BTM_CMD_STARTED;
2617 }
2618 else
2619 return BTM_NO_RESOURCES;
2620 }
2621 }
2622 /* If the inquire feature is on */
2623 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2624
2625 else if (origin == BTM_RMT_NAME_INQ)
2626 {
2627 /* If the database entry exists for the device, use its clock offset */
2628 if (p_cur)
2629 {
2630 cmd_ok = btsnd_hcic_rmt_name_req (remote_bda,
2631 p_cur->results.page_scan_rep_mode,
2632 p_cur->results.page_scan_mode,
2633 (UINT16)(p_cur->results.clock_offset |
2634 BTM_CLOCK_OFFSET_VALID));
2635 }
2636 else
2637 {
2638 cmd_ok = FALSE
2639 }
2640
2641 if (cmd_ok)
2642 return BTM_CMD_STARTED;
2643 else
2644 return BTM_NO_RESOURCES;
2645 }
2646 #endif
2647 else
2648 {
2649
2650 return BTM_ILLEGAL_VALUE;
2651
2652
2653 }
2654
2655
2656 }
2657
2658 /*******************************************************************************
2659 **
2660 ** Function btm_process_remote_name
2661 **
2662 ** Description This function is called when a remote name is received from
2663 ** the device. If remote names are cached, it updates the inquiry
2664 ** database.
2665 **
2666 ** Returns void
2667 **
2668 *******************************************************************************/
btm_process_remote_name(BD_ADDR bda,BD_NAME bdn,UINT16 evt_len,UINT8 hci_status)2669 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
2670 {
2671 tBTM_REMOTE_DEV_NAME rem_name;
2672 tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
2673 tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
2674 UINT8 *p_n1;
2675
2676 UINT16 temp_evt_len;
2677
2678 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2679 /*** These are only used if part of the Inquiry Process ***/
2680 tBTM_CMPL_CB *p_inq_cb;
2681 tINQ_DB_ENT *p_i = NULL;
2682 UINT8 *p_n;
2683 tBTM_INQ_INFO *p_cur;
2684 #endif
2685
2686 if (bda != NULL)
2687 {
2688 BTM_TRACE_EVENT("BDA %02x:%02x:%02x:%02x:%02x:%02x",bda[0], bda[1],
2689 bda[2], bda[3],
2690 bda[4], bda[5]);
2691 }
2692
2693 BTM_TRACE_EVENT("Inquire BDA %02x:%02x:%02x:%02x:%02x:%02x",p_inq->remname_bda[0], p_inq->remname_bda[1],
2694 p_inq->remname_bda[2], p_inq->remname_bda[3],
2695 p_inq->remname_bda[4], p_inq->remname_bda[5]);
2696
2697
2698
2699 /* If the inquire BDA and remote DBA are the same, then stop the timer and set the active to false */
2700 if ((p_inq->remname_active ==TRUE)&&
2701 (((bda != NULL) &&
2702 (memcmp(bda, p_inq->remname_bda,BD_ADDR_LEN)==0)) || bda == NULL))
2703
2704 {
2705 #if BLE_INCLUDED == TRUE
2706 if (BTM_UseLeLink(p_inq->remname_bda))
2707 {
2708 if (hci_status == HCI_ERR_UNSPECIFIED)
2709 btm_ble_cancel_remote_name(p_inq->remname_bda);
2710 }
2711 #endif
2712 btu_stop_timer (&p_inq->rmt_name_timer_ent);
2713 p_inq->remname_active = FALSE;
2714 /* Clean up and return the status if the command was not successful */
2715 /* Note: If part of the inquiry, the name is not stored, and the */
2716 /* inquiry complete callback is called. */
2717
2718 if ((hci_status == HCI_SUCCESS))
2719 {
2720 /* Copy the name from the data stream into the return structure */
2721 /* Note that even if it is not being returned, it is used as a */
2722 /* temporary buffer. */
2723 p_n1 = (UINT8 *)rem_name.remote_bd_name;
2724 rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
2725 rem_name.remote_bd_name[rem_name.length] = 0;
2726 rem_name.status = BTM_SUCCESS;
2727 temp_evt_len = rem_name.length;
2728
2729 while (temp_evt_len > 0)
2730 {
2731 *p_n1++ = *bdn++;
2732 temp_evt_len--;
2733 }
2734 rem_name.remote_bd_name[rem_name.length] = 0;
2735 }
2736
2737
2738 /* If processing a stand alone remote name then report the error in the callback */
2739 else
2740 {
2741 rem_name.status = BTM_BAD_VALUE_RET;
2742 rem_name.length = 0;
2743 rem_name.remote_bd_name[0] = 0;
2744 }
2745 /* Reset the remote BAD to zero and call callback if possible */
2746 memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
2747
2748 p_inq->p_remname_cmpl_cb = NULL;
2749 if (p_cb)
2750 (p_cb)((tBTM_REMOTE_DEV_NAME *)&rem_name);
2751 }
2752
2753
2754 #if (BTM_INQ_GET_REMOTE_NAME==TRUE)
2755 /* If existing entry, update the name */
2756 if ((bda != NULL) && ((p_i = btm_inq_db_find (bda)) != NULL)
2757 && (hci_status == HCI_SUCCESS))
2758 {
2759 p_i->inq_info.remote_name_state = BTM_INQ_RMT_NAME_DONE;
2760 p_n = p_i->inq_info.remote_name;
2761 memset(p_n, 0, BTM_MAX_REM_BD_NAME_LEN + 1);
2762 p_i->inq_info.remote_name_len = (rem_name.length < BTM_MAX_REM_BD_NAME_LEN) ?
2763 rem_name.length : BTM_MAX_REM_BD_NAME_LEN;
2764 evt_len = p_i->inq_info.remote_name_len;
2765 p_n1 = (UINT8 *)rem_name.remote_bd_name;
2766 while (evt_len > 0)
2767 {
2768 *p_n++ = *p_n1++;
2769 evt_len--;
2770 }
2771
2772 if (btm_cb.btm_inq_vars.p_inq_change_cb)
2773 (*btm_cb.btm_inq_vars.p_inq_change_cb) (&p_i->inq_info, TRUE);
2774 }
2775 else
2776 {
2777 if (p_i)
2778 p_i->inq_info.remote_name_state = BTM_INQ_RMT_NAME_FAILED;
2779 else
2780 {
2781 /* Find the entry which is currently doing name request */
2782 for (p_cur = BTM_InqDbFirst(); p_cur; p_cur = BTM_InqDbNext (p_cur))
2783 {
2784 if (p_cur->remote_name_state == BTM_INQ_RMT_NAME_PENDING)
2785 {
2786 /* Should be only one */
2787 p_cur->remote_name_state = BTM_INQ_RMT_NAME_FAILED;
2788 break;
2789 }
2790 }
2791 }
2792 }
2793
2794 /* If an inquiry is in progress then update other entries */
2795 if (p_inq->inq_active)
2796 {
2797 /* Check if there are any more entries inquired but not named */
2798 for (p_cur = BTM_InqDbFirst(); p_cur; p_cur = BTM_InqDbNext (p_cur))
2799 {
2800 if (p_cur->remote_name_state == BTM_INQ_RMT_NAME_EMPTY)
2801 {
2802 p_cur->remote_name_state = BTM_INQ_RMT_NAME_PENDING;
2803 #if (BLE_INCLUDED == TRUE)
2804 if (BTM_UseLeLink(remote_bda))
2805 {
2806 if (btm_ble_read_remote_name(remote_bda, p_cur, p_cb) != BTM_CMD_STARTED)
2807 p_cur->remote_name_state = BTM_INQ_RMT_NAME_FAILED;
2808 else
2809 return;
2810 }
2811 else
2812 #endif
2813 {
2814 if (btm_initiate_rem_name (p_cur->results.remote_bd_addr,
2815 p_cur, BTM_RMT_NAME_INQ,
2816 BTM_INQ_RMT_NAME_TIMEOUT, NULL) != BTM_CMD_STARTED)
2817 p_cur->remote_name_state = BTM_INQ_RMT_NAME_FAILED;
2818 else
2819 return;
2820 }
2821 }
2822 }
2823
2824 /* The inquiry has finished so call the callback for the inquiry */
2825 p_inq_cb = p_inq->p_inq_cmpl_cb;
2826 p_inq->state = BTM_INQ_INACTIVE_STATE;
2827 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
2828 p_inq->p_inq_cmpl_cb = NULL;
2829
2830 /* If we have a callback registered for inquiry complete, call it */
2831 if (p_inq_cb)
2832 (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
2833
2834 /* In some cases we can not get name of the device once but will be */
2835 /* able to do it next time. Until we have better solution we will */
2836 /* try to get name every time */
2837 for (p_cur = BTM_InqDbFirst(); p_cur; p_cur = BTM_InqDbNext (p_cur))
2838 {
2839 if (p_cur->remote_name_state == BTM_INQ_RMT_NAME_FAILED)
2840 p_cur->remote_name_state = BTM_INQ_RMT_NAME_EMPTY;
2841 }
2842 }
2843 #endif /* BTM_INQ_GET_REMOTE_NAME == TRUE */
2844 }
2845
2846 /*******************************************************************************
2847 **
2848 ** Function btm_inq_rmt_name_failed
2849 **
2850 ** Description This function is if timeout expires while getting remote
2851 ** name. This is done for devices that incorrectly do not
2852 ** report operation failure
2853 **
2854 ** Returns void
2855 **
2856 *******************************************************************************/
btm_inq_rmt_name_failed(void)2857 void btm_inq_rmt_name_failed (void)
2858 {
2859 BTM_TRACE_ERROR ("btm_inq_rmt_name_failed() remname_active=%d", btm_cb.btm_inq_vars.remname_active);
2860
2861 if (btm_cb.btm_inq_vars.remname_active)
2862 btm_process_remote_name (btm_cb.btm_inq_vars.remname_bda, NULL, 0, HCI_ERR_UNSPECIFIED);
2863 else
2864 btm_process_remote_name (NULL, NULL, 0, HCI_ERR_UNSPECIFIED);
2865
2866 btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED);
2867 }
2868 /*******************************************************************************
2869 **
2870 ** Function btm_read_linq_tx_power_complete
2871 **
2872 ** Description read inquiry tx power level complete callback function.
2873 **
2874 ** Returns void
2875 **
2876 *******************************************************************************/
btm_read_linq_tx_power_complete(UINT8 * p)2877 void btm_read_linq_tx_power_complete(UINT8 *p)
2878 {
2879 tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb;
2880 tBTM_INQ_TXPWR_RESULTS results;
2881
2882 btu_stop_timer (&btm_cb.devcb.txpwer_timer);
2883 /* If there was a callback registered for read inq tx power, call it */
2884 btm_cb.devcb.p_txpwer_cmpl_cb = NULL;
2885
2886 if (p_cb)
2887 {
2888 STREAM_TO_UINT8 (results.hci_status, p);
2889
2890 if (results.hci_status == HCI_SUCCESS)
2891 {
2892 results.status = BTM_SUCCESS;
2893
2894 STREAM_TO_UINT8 (results.tx_power, p);
2895 BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x",
2896 results.tx_power, results.hci_status);
2897 }
2898 else
2899 results.status = BTM_ERR_PROCESSING;
2900
2901 (*p_cb)(&results);
2902 }
2903
2904 }
2905 /*******************************************************************************
2906 **
2907 ** Function BTM_WriteEIR
2908 **
2909 ** Description This function is called to write EIR data to controller.
2910 **
2911 ** Parameters p_buff - allocated HCI command buffer including extended
2912 ** inquriry response
2913 **
2914 ** Returns BTM_SUCCESS - if successful
2915 ** BTM_MODE_UNSUPPORTED - if local device cannot support it
2916 **
2917 *******************************************************************************/
BTM_WriteEIR(BT_HDR * p_buff)2918 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
2919 {
2920 #if (BTM_EIR_SERVER_INCLUDED == TRUE)
2921 if (HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
2922 {
2923 BTM_TRACE_API("Write Extended Inquiry Response to controller");
2924 btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
2925 return BTM_SUCCESS;
2926 }
2927 else
2928 {
2929 GKI_freebuf(p_buff);
2930 return BTM_MODE_UNSUPPORTED;
2931 }
2932 #else
2933 GKI_freebuf(p_buff);
2934 return BTM_SUCCESS;
2935 #endif
2936 }
2937
2938 /*******************************************************************************
2939 **
2940 ** Function BTM_CheckEirData
2941 **
2942 ** Description This function is called to get EIR data from significant part.
2943 **
2944 ** Parameters p_eir - pointer of EIR significant part
2945 ** type - finding EIR data type
2946 ** p_length - return the length of EIR data not including type
2947 **
2948 ** Returns pointer of EIR data
2949 **
2950 *******************************************************************************/
BTM_CheckEirData(UINT8 * p_eir,UINT8 type,UINT8 * p_length)2951 UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
2952 {
2953 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
2954 UINT8 *p = p_eir;
2955 UINT8 length;
2956 UINT8 eir_type;
2957 BTM_TRACE_API("BTM_CheckEirData type=0x%02X", type);
2958
2959 STREAM_TO_UINT8(length, p);
2960 while( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN))
2961 {
2962 STREAM_TO_UINT8(eir_type, p);
2963 if( eir_type == type )
2964 {
2965 /* length doesn't include itself */
2966 *p_length = length - 1; /* minus the length of type */
2967 return p;
2968 }
2969 p += length - 1; /* skip the length of data */
2970 STREAM_TO_UINT8(length, p);
2971 }
2972
2973 *p_length = 0;
2974 return NULL;
2975 #else
2976 return NULL;
2977 #endif
2978 }
2979
2980 /*******************************************************************************
2981 **
2982 ** Function btm_convert_uuid_to_eir_service
2983 **
2984 ** Description This function is called to get the bit position of UUID.
2985 **
2986 ** Parameters uuid16 - UUID 16-bit
2987 **
2988 ** Returns BTM EIR service ID if found
2989 ** BTM_EIR_MAX_SERVICES - if not found
2990 **
2991 *******************************************************************************/
2992 #if (( BTM_EIR_CLIENT_INCLUDED == TRUE )||( BTM_EIR_SERVER_INCLUDED == TRUE ))
btm_convert_uuid_to_eir_service(UINT16 uuid16)2993 static UINT8 btm_convert_uuid_to_eir_service( UINT16 uuid16 )
2994 {
2995 UINT8 xx;
2996
2997 for( xx = 0; xx < BTM_EIR_MAX_SERVICES; xx++ )
2998 {
2999 if( uuid16 == BTM_EIR_UUID_LKUP_TBL[xx])
3000 {
3001 return xx;
3002 }
3003 }
3004 return BTM_EIR_MAX_SERVICES;
3005 }
3006 #endif
3007
3008 /*******************************************************************************
3009 **
3010 ** Function BTM_HasEirService
3011 **
3012 ** Description This function is called to know if UUID in bit map of UUID.
3013 **
3014 ** Parameters p_eir_uuid - bit map of UUID list
3015 ** uuid16 - UUID 16-bit
3016 **
3017 ** Returns TRUE - if found
3018 ** FALSE - if not found
3019 **
3020 *******************************************************************************/
BTM_HasEirService(UINT32 * p_eir_uuid,UINT16 uuid16)3021 BOOLEAN BTM_HasEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
3022 {
3023 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
3024 UINT8 service_id;
3025
3026 service_id = btm_convert_uuid_to_eir_service(uuid16);
3027 if( service_id < BTM_EIR_MAX_SERVICES )
3028 return( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_id ));
3029 else
3030 return( FALSE );
3031 #else
3032 return( FALSE );
3033 #endif
3034 }
3035
3036 /*******************************************************************************
3037 **
3038 ** Function BTM_HasInquiryEirService
3039 **
3040 ** Description This function is called to know if UUID in bit map of UUID list.
3041 **
3042 ** Parameters p_results - inquiry results
3043 ** uuid16 - UUID 16-bit
3044 **
3045 ** Returns BTM_EIR_FOUND - if found
3046 ** BTM_EIR_NOT_FOUND - if not found and it is complete list
3047 ** BTM_EIR_UNKNOWN - if not found and it is not complete list
3048 **
3049 *******************************************************************************/
BTM_HasInquiryEirService(tBTM_INQ_RESULTS * p_results,UINT16 uuid16)3050 tBTM_EIR_SEARCH_RESULT BTM_HasInquiryEirService( tBTM_INQ_RESULTS *p_results, UINT16 uuid16 )
3051 {
3052 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
3053 if( BTM_HasEirService( p_results->eir_uuid, uuid16 ))
3054 {
3055 return BTM_EIR_FOUND;
3056 }
3057 else if( p_results->eir_complete_list )
3058 {
3059 return BTM_EIR_NOT_FOUND;
3060 }
3061 else
3062 return BTM_EIR_UNKNOWN;
3063 #else
3064 return BTM_EIR_UNKNOWN;
3065 #endif
3066 }
3067
3068 /*******************************************************************************
3069 **
3070 ** Function BTM_AddEirService
3071 **
3072 ** Description This function is called to add a service in bit map of UUID list.
3073 **
3074 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
3075 ** uuid16 - UUID 16-bit
3076 **
3077 ** Returns None
3078 **
3079 *******************************************************************************/
BTM_AddEirService(UINT32 * p_eir_uuid,UINT16 uuid16)3080 void BTM_AddEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
3081 {
3082 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
3083 UINT8 service_id;
3084
3085 service_id = btm_convert_uuid_to_eir_service(uuid16);
3086 if( service_id < BTM_EIR_MAX_SERVICES )
3087 BTM_EIR_SET_SERVICE( p_eir_uuid, service_id );
3088 #endif
3089 }
3090
3091 /*******************************************************************************
3092 **
3093 ** Function BTM_RemoveEirService
3094 **
3095 ** Description This function is called to remove a service in bit map of UUID list.
3096 **
3097 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
3098 ** uuid16 - UUID 16-bit
3099 **
3100 ** Returns None
3101 **
3102 *******************************************************************************/
BTM_RemoveEirService(UINT32 * p_eir_uuid,UINT16 uuid16)3103 void BTM_RemoveEirService( UINT32 *p_eir_uuid, UINT16 uuid16 )
3104 {
3105 #if (BTM_EIR_SERVER_INCLUDED == TRUE)
3106 UINT8 service_id;
3107
3108 service_id = btm_convert_uuid_to_eir_service(uuid16);
3109 if( service_id < BTM_EIR_MAX_SERVICES )
3110 BTM_EIR_CLR_SERVICE( p_eir_uuid, service_id );
3111 #endif
3112 }
3113
3114 /*******************************************************************************
3115 **
3116 ** Function BTM_GetEirSupportedServices
3117 **
3118 ** Description This function is called to get UUID list from bit map of UUID list.
3119 **
3120 ** Parameters p_eir_uuid - bit mask of UUID list for EIR
3121 ** p - reference of current pointer of EIR
3122 ** max_num_uuid16 - max number of UUID can be written in EIR
3123 ** num_uuid16 - number of UUID have been written in EIR
3124 **
3125 ** Returns BTM_EIR_MORE_16BITS_UUID_TYPE, if it has more than max
3126 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE, otherwise
3127 **
3128 *******************************************************************************/
BTM_GetEirSupportedServices(UINT32 * p_eir_uuid,UINT8 ** p,UINT8 max_num_uuid16,UINT8 * p_num_uuid16)3129 UINT8 BTM_GetEirSupportedServices( UINT32 *p_eir_uuid, UINT8 **p,
3130 UINT8 max_num_uuid16, UINT8 *p_num_uuid16)
3131 {
3132 #if (BTM_EIR_SERVER_INCLUDED == TRUE)
3133 UINT8 service_index;
3134
3135 *p_num_uuid16 = 0;
3136
3137 for(service_index = 0; service_index < BTM_EIR_MAX_SERVICES; service_index++)
3138 {
3139 if( BTM_EIR_HAS_SERVICE( p_eir_uuid, service_index ))
3140 {
3141 if( *p_num_uuid16 < max_num_uuid16 )
3142 {
3143 UINT16_TO_STREAM(*p, BTM_EIR_UUID_LKUP_TBL[service_index]);
3144 (*p_num_uuid16)++;
3145 }
3146 /* if max number of UUIDs are stored and found one more */
3147 else
3148 {
3149 return BTM_EIR_MORE_16BITS_UUID_TYPE;
3150 }
3151 }
3152 }
3153 return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
3154 #else
3155 return BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
3156 #endif
3157 }
3158
3159 /*******************************************************************************
3160 **
3161 ** Function BTM_GetEirUuidList
3162 **
3163 ** Description This function parses EIR and returns UUID list.
3164 **
3165 ** Parameters p_eir - EIR
3166 ** uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
3167 ** p_num_uuid - return number of UUID in found list
3168 ** p_uuid_list - return UUID list
3169 ** max_num_uuid - maximum number of UUID to be returned
3170 **
3171 ** Returns 0 - if not found
3172 ** BTM_EIR_COMPLETE_16BITS_UUID_TYPE
3173 ** BTM_EIR_MORE_16BITS_UUID_TYPE
3174 ** BTM_EIR_COMPLETE_32BITS_UUID_TYPE
3175 ** BTM_EIR_MORE_32BITS_UUID_TYPE
3176 ** BTM_EIR_COMPLETE_128BITS_UUID_TYPE
3177 ** BTM_EIR_MORE_128BITS_UUID_TYPE
3178 **
3179 *******************************************************************************/
BTM_GetEirUuidList(UINT8 * p_eir,UINT8 uuid_size,UINT8 * p_num_uuid,UINT8 * p_uuid_list,UINT8 max_num_uuid)3180 UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
3181 UINT8 *p_uuid_list, UINT8 max_num_uuid)
3182 {
3183 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
3184 UINT8 *p_uuid_data;
3185 UINT8 type;
3186 UINT8 yy, xx;
3187 UINT16 *p_uuid16 = (UINT16 *)p_uuid_list;
3188 UINT32 *p_uuid32 = (UINT32 *)p_uuid_list;
3189 char buff[LEN_UUID_128 * 2 + 1];
3190
3191 p_uuid_data = btm_eir_get_uuid_list( p_eir, uuid_size, p_num_uuid, &type );
3192 if( p_uuid_data == NULL )
3193 {
3194 return 0x00;
3195 }
3196
3197 if( *p_num_uuid > max_num_uuid )
3198 {
3199 BTM_TRACE_WARNING("BTM_GetEirUuidList number of uuid in EIR = %d, size of uuid list = %d",
3200 *p_num_uuid, max_num_uuid );
3201 *p_num_uuid = max_num_uuid;
3202 }
3203
3204 BTM_TRACE_DEBUG("BTM_GetEirUuidList type = %02X, number of uuid = %d", type, *p_num_uuid );
3205
3206 if( uuid_size == LEN_UUID_16 )
3207 {
3208 for( yy = 0; yy < *p_num_uuid; yy++ )
3209 {
3210 STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
3211 BTM_TRACE_DEBUG(" 0x%04X", *(p_uuid16 + yy));
3212 }
3213 }
3214 else if( uuid_size == LEN_UUID_32 )
3215 {
3216 for( yy = 0; yy < *p_num_uuid; yy++ )
3217 {
3218 STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
3219 BTM_TRACE_DEBUG(" 0x%08X", *(p_uuid32 + yy));
3220 }
3221 }
3222 else if( uuid_size == LEN_UUID_128 )
3223 {
3224 for( yy = 0; yy < *p_num_uuid; yy++ )
3225 {
3226 STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
3227 for( xx = 0; xx < LEN_UUID_128; xx++ )
3228 sprintf(buff + xx*2, "%02X", *(p_uuid_list + yy * LEN_UUID_128 + xx));
3229 BTM_TRACE_DEBUG(" 0x%s", buff);
3230 }
3231 }
3232
3233 return type;
3234 #else
3235 *p_num_uuid = 0;
3236 return 0x00;
3237 #endif
3238 }
3239
3240
3241 #if (BTM_EIR_CLIENT_INCLUDED == TRUE)
3242 /*******************************************************************************
3243 **
3244 ** Function btm_eir_get_uuid_list
3245 **
3246 ** Description This function searches UUID list in EIR.
3247 **
3248 ** Parameters p_eir - address of EIR
3249 ** uuid_size - size of UUID to find
3250 ** p_num_uuid - number of UUIDs found
3251 ** p_uuid_list_type - EIR data type
3252 **
3253 ** Returns NULL - if UUID list with uuid_size is not found
3254 ** beginning of UUID list in EIR - otherwise
3255 **
3256 *******************************************************************************/
btm_eir_get_uuid_list(UINT8 * p_eir,UINT8 uuid_size,UINT8 * p_num_uuid,UINT8 * p_uuid_list_type)3257 static UINT8 *btm_eir_get_uuid_list( UINT8 *p_eir, UINT8 uuid_size,
3258 UINT8 *p_num_uuid, UINT8 *p_uuid_list_type )
3259 {
3260 UINT8 *p_uuid_data;
3261 UINT8 complete_type, more_type;
3262 UINT8 uuid_len;
3263
3264 switch( uuid_size )
3265 {
3266 case LEN_UUID_16:
3267 complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
3268 more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
3269 break;
3270 case LEN_UUID_32:
3271 complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
3272 more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
3273 break;
3274 case LEN_UUID_128:
3275 complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
3276 more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
3277 break;
3278 default:
3279 *p_num_uuid = 0;
3280 return NULL;
3281 break;
3282 }
3283
3284 p_uuid_data = BTM_CheckEirData( p_eir, complete_type, &uuid_len );
3285 if(p_uuid_data == NULL)
3286 {
3287 p_uuid_data = BTM_CheckEirData( p_eir, more_type, &uuid_len );
3288 *p_uuid_list_type = more_type;
3289 }
3290 else
3291 {
3292 *p_uuid_list_type = complete_type;
3293 }
3294
3295 *p_num_uuid = uuid_len / uuid_size;
3296 return p_uuid_data;
3297 }
3298
3299 /*******************************************************************************
3300 **
3301 ** Function btm_convert_uuid_to_uuid16
3302 **
3303 ** Description This function converts UUID to UUID 16-bit.
3304 **
3305 ** Parameters p_uuid - address of UUID
3306 ** uuid_size - size of UUID
3307 **
3308 ** Returns 0 - if UUID cannot be converted to UUID 16-bit
3309 ** UUID 16-bit - otherwise
3310 **
3311 *******************************************************************************/
btm_convert_uuid_to_uuid16(UINT8 * p_uuid,UINT8 uuid_size)3312 static UINT16 btm_convert_uuid_to_uuid16( UINT8 *p_uuid, UINT8 uuid_size )
3313 {
3314 static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
3315 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3316 UINT16 uuid16 = 0;
3317 UINT32 uuid32;
3318 BOOLEAN is_base_uuid;
3319 UINT8 xx;
3320
3321 switch (uuid_size)
3322 {
3323 case LEN_UUID_16:
3324 STREAM_TO_UINT16 (uuid16, p_uuid);
3325 break;
3326 case LEN_UUID_32:
3327 STREAM_TO_UINT32 (uuid32, p_uuid);
3328 if (uuid32 < 0x10000)
3329 uuid16 = (UINT16) uuid32;
3330 break;
3331 case LEN_UUID_128:
3332 /* See if we can compress his UUID down to 16 or 32bit UUIDs */
3333 is_base_uuid = TRUE;
3334 for (xx = 0; xx < LEN_UUID_128 - 4; xx++)
3335 {
3336 if (p_uuid[xx] != base_uuid[xx])
3337 {
3338 is_base_uuid = FALSE;
3339 break;
3340 }
3341 }
3342 if (is_base_uuid)
3343 {
3344 if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0))
3345 {
3346 p_uuid += (LEN_UUID_128 - 4);
3347 STREAM_TO_UINT16(uuid16, p_uuid);
3348 }
3349 }
3350 break;
3351 default:
3352 BTM_TRACE_WARNING("btm_convert_uuid_to_uuid16 invalid uuid size");
3353 break;
3354 }
3355
3356 return( uuid16);
3357 }
3358
3359 /*******************************************************************************
3360 **
3361 ** Function btm_set_eir_uuid
3362 **
3363 ** Description This function is called to store received UUID into inquiry result.
3364 **
3365 ** Parameters p_eir - pointer of EIR significant part
3366 ** p_results - pointer of inquiry result
3367 **
3368 ** Returns None
3369 **
3370 *******************************************************************************/
btm_set_eir_uuid(UINT8 * p_eir,tBTM_INQ_RESULTS * p_results)3371 void btm_set_eir_uuid( UINT8 *p_eir, tBTM_INQ_RESULTS *p_results )
3372 {
3373 UINT8 *p_uuid_data;
3374 UINT8 num_uuid;
3375 UINT16 uuid16;
3376 UINT8 yy;
3377 UINT8 type = BTM_EIR_MORE_16BITS_UUID_TYPE;
3378
3379 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_16, &num_uuid, &type );
3380
3381 if(type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE)
3382 {
3383 p_results->eir_complete_list = TRUE;
3384 }
3385 else
3386 {
3387 p_results->eir_complete_list = FALSE;
3388 }
3389
3390 BTM_TRACE_API("btm_set_eir_uuid eir_complete_list=0x%02X", p_results->eir_complete_list);
3391
3392 if( p_uuid_data )
3393 {
3394 for( yy = 0; yy < num_uuid; yy++ )
3395 {
3396 STREAM_TO_UINT16(uuid16, p_uuid_data);
3397 BTM_AddEirService( p_results->eir_uuid, uuid16 );
3398 }
3399 }
3400
3401 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_32, &num_uuid, &type );
3402 if( p_uuid_data )
3403 {
3404 for( yy = 0; yy < num_uuid; yy++ )
3405 {
3406 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_32 );
3407 p_uuid_data += LEN_UUID_32;
3408 if( uuid16 )
3409 BTM_AddEirService( p_results->eir_uuid, uuid16 );
3410 }
3411 }
3412
3413 p_uuid_data = btm_eir_get_uuid_list( p_eir, LEN_UUID_128, &num_uuid, &type );
3414 if( p_uuid_data )
3415 {
3416 for( yy = 0; yy < num_uuid; yy++ )
3417 {
3418 uuid16 = btm_convert_uuid_to_uuid16( p_uuid_data, LEN_UUID_128 );
3419 p_uuid_data += LEN_UUID_128;
3420 if( uuid16 )
3421 BTM_AddEirService( p_results->eir_uuid, uuid16 );
3422 }
3423 }
3424 }
3425 #endif
3426
3427