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