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