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