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