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