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