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