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