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