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