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