bta_hh_co.cc revision 6bd442f543972b072ef2cbbcf2f7c91202de1045
1/****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19#include <assert.h> 20#include <ctype.h> 21#include <errno.h> 22#include <fcntl.h> 23#include <linux/uhid.h> 24#include <pthread.h> 25#include <stdint.h> 26#include <stdio.h> 27#include <string.h> 28#include <sys/poll.h> 29#include <unistd.h> 30 31#include "bta_api.h" 32#include "bta_hh_api.h" 33#include "bta_hh_co.h" 34#include "btcore/include/bdaddr.h" 35#include "btif_hh.h" 36#include "btif_util.h" 37#include "osi/include/osi.h" 38 39const char* dev_path = "/dev/uhid"; 40 41#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) 42#include "btif_config.h" 43#define BTA_HH_NV_LOAD_MAX 16 44static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; 45#endif 46 47void uhid_set_non_blocking(int fd) { 48 int opts = fcntl(fd, F_GETFL); 49 if (opts < 0) 50 APPL_TRACE_ERROR("%s() Getting flags failed (%s)", __func__, 51 strerror(errno)); 52 53 opts |= O_NONBLOCK; 54 55 if (fcntl(fd, F_SETFL, opts) < 0) 56 APPL_TRACE_EVENT("%s() Setting non-blocking flag failed (%s)", __func__, 57 strerror(errno)); 58} 59 60/*Internal function to perform UHID write and error checking*/ 61static int uhid_write(int fd, const struct uhid_event* ev) { 62 ssize_t ret; 63 OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev))); 64 65 if (ret < 0) { 66 int rtn = -errno; 67 APPL_TRACE_ERROR("%s: Cannot write to uhid:%s", __func__, strerror(errno)); 68 return rtn; 69 } else if (ret != (ssize_t)sizeof(*ev)) { 70 APPL_TRACE_ERROR("%s: Wrong size written to uhid: %zd != %zu", __func__, 71 ret, sizeof(*ev)); 72 return -EFAULT; 73 } 74 75 return 0; 76} 77 78/* Internal function to parse the events received from UHID driver*/ 79static int uhid_read_event(btif_hh_device_t* p_dev) { 80 assert(p_dev); 81 82 struct uhid_event ev; 83 memset(&ev, 0, sizeof(ev)); 84 85 ssize_t ret; 86 OSI_NO_INTR(ret = read(p_dev->fd, &ev, sizeof(ev))); 87 88 if (ret == 0) { 89 APPL_TRACE_ERROR("%s: Read HUP on uhid-cdev %s", __func__, strerror(errno)); 90 return -EFAULT; 91 } else if (ret < 0) { 92 APPL_TRACE_ERROR("%s: Cannot read uhid-cdev: %s", __func__, 93 strerror(errno)); 94 return -errno; 95 } 96 97 switch (ev.type) { 98 case UHID_START: 99 APPL_TRACE_DEBUG("UHID_START from uhid-dev\n"); 100 p_dev->ready_for_data = true; 101 break; 102 case UHID_STOP: 103 APPL_TRACE_DEBUG("UHID_STOP from uhid-dev\n"); 104 p_dev->ready_for_data = false; 105 break; 106 case UHID_OPEN: 107 APPL_TRACE_DEBUG("UHID_OPEN from uhid-dev\n"); 108 p_dev->ready_for_data = true; 109 break; 110 case UHID_CLOSE: 111 APPL_TRACE_DEBUG("UHID_CLOSE from uhid-dev\n"); 112 p_dev->ready_for_data = false; 113 break; 114 case UHID_OUTPUT: 115 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) { 116 APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", 117 __func__, ret, sizeof(ev.type) + sizeof(ev.u.output)); 118 return -EFAULT; 119 } 120 121 APPL_TRACE_DEBUG("UHID_OUTPUT: Report type = %d, report_size = %d", 122 ev.u.output.rtype, ev.u.output.size); 123 // Send SET_REPORT with feature report if the report type in output event 124 // is FEATURE 125 if (ev.u.output.rtype == UHID_FEATURE_REPORT) 126 btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT, ev.u.output.size, 127 ev.u.output.data); 128 else if (ev.u.output.rtype == UHID_OUTPUT_REPORT) 129 btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT, ev.u.output.size, 130 ev.u.output.data); 131 else 132 btif_hh_setreport(p_dev, BTHH_INPUT_REPORT, ev.u.output.size, 133 ev.u.output.data); 134 break; 135 case UHID_OUTPUT_EV: 136 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output_ev))) { 137 APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", 138 __func__, ret, 139 sizeof(ev.type) + sizeof(ev.u.output_ev)); 140 return -EFAULT; 141 } 142 APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n"); 143 break; 144 case UHID_FEATURE: 145 APPL_TRACE_DEBUG("UHID_FEATURE from uhid-dev\n"); 146 break; 147 case UHID_FEATURE_ANSWER: 148 APPL_TRACE_DEBUG("UHID_FEATURE_ANSWER from uhid-dev\n"); 149 break; 150 151 default: 152 APPL_TRACE_DEBUG("Invalid event from uhid-dev: %u\n", ev.type); 153 } 154 155 return 0; 156} 157 158/******************************************************************************* 159 * 160 * Function create_thread 161 * 162 * Description creat a select loop 163 * 164 * Returns pthread_t 165 * 166 ******************************************************************************/ 167static inline pthread_t create_thread(void* (*start_routine)(void*), 168 void* arg) { 169 APPL_TRACE_DEBUG("create_thread: entered"); 170 pthread_attr_t thread_attr; 171 172 pthread_attr_init(&thread_attr); 173 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 174 pthread_t thread_id = -1; 175 if (pthread_create(&thread_id, &thread_attr, start_routine, arg) != 0) { 176 APPL_TRACE_ERROR("pthread_create : %s", strerror(errno)); 177 return -1; 178 } 179 APPL_TRACE_DEBUG("create_thread: thread created successfully"); 180 return thread_id; 181} 182 183/******************************************************************************* 184 * 185 * Function btif_hh_poll_event_thread 186 * 187 * Description the polling thread which polls for event from UHID driver 188 * 189 * Returns void 190 * 191 ******************************************************************************/ 192static void* btif_hh_poll_event_thread(void* arg) { 193 btif_hh_device_t* p_dev = (btif_hh_device_t*)arg; 194 APPL_TRACE_DEBUG("%s: Thread created fd = %d", __func__, p_dev->fd); 195 struct pollfd pfds[1]; 196 197 pfds[0].fd = p_dev->fd; 198 pfds[0].events = POLLIN; 199 200 // Set the uhid fd as non-blocking to ensure we never block the BTU thread 201 uhid_set_non_blocking(p_dev->fd); 202 203 while (p_dev->hh_keep_polling) { 204 int ret; 205 OSI_NO_INTR(ret = poll(pfds, 1, 50)); 206 if (ret < 0) { 207 APPL_TRACE_ERROR("%s: Cannot poll for fds: %s\n", __func__, 208 strerror(errno)); 209 break; 210 } 211 if (pfds[0].revents & POLLIN) { 212 APPL_TRACE_DEBUG("%s: POLLIN", __func__); 213 ret = uhid_read_event(p_dev); 214 if (ret != 0) break; 215 } 216 } 217 218 p_dev->hh_poll_thread_id = -1; 219 return 0; 220} 221 222static inline void btif_hh_close_poll_thread(btif_hh_device_t* p_dev) { 223 APPL_TRACE_DEBUG("%s", __func__); 224 p_dev->hh_keep_polling = 0; 225 if (p_dev->hh_poll_thread_id > 0) 226 pthread_join(p_dev->hh_poll_thread_id, NULL); 227 228 return; 229} 230 231void bta_hh_co_destroy(int fd) { 232 struct uhid_event ev; 233 memset(&ev, 0, sizeof(ev)); 234 ev.type = UHID_DESTROY; 235 uhid_write(fd, &ev); 236 APPL_TRACE_DEBUG("%s: Closing fd=%d", __func__, fd); 237 close(fd); 238} 239 240int bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len) { 241 APPL_TRACE_DEBUG("%s: UHID write %d", __func__, len); 242 243 struct uhid_event ev; 244 memset(&ev, 0, sizeof(ev)); 245 ev.type = UHID_INPUT; 246 ev.u.input.size = len; 247 if (len > sizeof(ev.u.input.data)) { 248 APPL_TRACE_WARNING("%s: Report size greater than allowed size", __func__); 249 return -1; 250 } 251 memcpy(ev.u.input.data, rpt, len); 252 253 return uhid_write(fd, &ev); 254} 255 256/******************************************************************************* 257 * 258 * Function bta_hh_co_open 259 * 260 * Description When connection is opened, this call-out function is executed 261 * by HH to do platform specific initialization. 262 * 263 * Returns void. 264 ******************************************************************************/ 265void bta_hh_co_open(uint8_t dev_handle, uint8_t sub_class, 266 tBTA_HH_ATTR_MASK attr_mask, uint8_t app_id) { 267 uint32_t i; 268 btif_hh_device_t* p_dev = NULL; 269 270 if (dev_handle == BTA_HH_INVALID_HANDLE) { 271 APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, 272 dev_handle); 273 return; 274 } 275 276 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 277 p_dev = &btif_hh_cb.devices[i]; 278 if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && 279 p_dev->dev_handle == dev_handle) { 280 // We found a device with the same handle. Must be a device reconnected. 281 APPL_TRACE_WARNING( 282 "%s: Found an existing device with the same handle " 283 "dev_status = %d", 284 __func__, p_dev->dev_status); 285 APPL_TRACE_WARNING("%s: bd_addr = [%02X:%02X:%02X:%02X:%02X:]", 286 __func__, p_dev->bd_addr.address[0], 287 p_dev->bd_addr.address[1], p_dev->bd_addr.address[2], 288 p_dev->bd_addr.address[3], p_dev->bd_addr.address[4]); 289 APPL_TRACE_WARNING( 290 "%s: attr_mask = 0x%04x, sub_class = 0x%02x, app_id = %d", 291 __func__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id); 292 293 if (p_dev->fd < 0) { 294 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC); 295 if (p_dev->fd < 0) { 296 APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", __func__, 297 strerror(errno)); 298 return; 299 } else 300 APPL_TRACE_DEBUG("%s: uhid fd = %d", __func__, p_dev->fd); 301 } 302 303 p_dev->hh_keep_polling = 1; 304 p_dev->hh_poll_thread_id = 305 create_thread(btif_hh_poll_event_thread, p_dev); 306 break; 307 } 308 p_dev = NULL; 309 } 310 311 if (p_dev == NULL) { 312 // Did not find a device reconnection case. Find an empty slot now. 313 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 314 if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_UNKNOWN) { 315 p_dev = &btif_hh_cb.devices[i]; 316 p_dev->dev_handle = dev_handle; 317 p_dev->attr_mask = attr_mask; 318 p_dev->sub_class = sub_class; 319 p_dev->app_id = app_id; 320 p_dev->local_vup = false; 321 322 btif_hh_cb.device_num++; 323 // This is a new device,open the uhid driver now. 324 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC); 325 if (p_dev->fd < 0) { 326 APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", __func__, 327 strerror(errno)); 328 return; 329 } else { 330 APPL_TRACE_DEBUG("%s: uhid fd = %d", __func__, p_dev->fd); 331 p_dev->hh_keep_polling = 1; 332 p_dev->hh_poll_thread_id = 333 create_thread(btif_hh_poll_event_thread, p_dev); 334 } 335 336 break; 337 } 338 } 339 } 340 341 if (p_dev == NULL) { 342 APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__); 343 return; 344 } 345 346 p_dev->dev_status = BTHH_CONN_STATE_CONNECTED; 347 APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status); 348} 349 350/******************************************************************************* 351 * 352 * Function bta_hh_co_close 353 * 354 * Description When connection is closed, this call-out function is executed 355 * by HH to do platform specific finalization. 356 * 357 * Parameters dev_handle - device handle 358 * app_id - application id 359 * 360 * Returns void. 361 ******************************************************************************/ 362void bta_hh_co_close(uint8_t dev_handle, uint8_t app_id) { 363 uint32_t i; 364 btif_hh_device_t* p_dev = NULL; 365 366 APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __func__, dev_handle, 367 app_id); 368 if (dev_handle == BTA_HH_INVALID_HANDLE) { 369 APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, 370 dev_handle); 371 return; 372 } 373 374 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 375 p_dev = &btif_hh_cb.devices[i]; 376 if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && 377 p_dev->dev_handle == dev_handle) { 378 APPL_TRACE_WARNING( 379 "%s: Found an existing device with the same handle " 380 "dev_status = %d, dev_handle =%d", 381 __func__, p_dev->dev_status, p_dev->dev_handle); 382 btif_hh_close_poll_thread(p_dev); 383 break; 384 } 385 } 386} 387 388/******************************************************************************* 389 * 390 * Function bta_hh_co_data 391 * 392 * Description This function is executed by BTA when HID host receive a 393 *data 394 * report. 395 * 396 * Parameters dev_handle - device handle 397 * *p_rpt - pointer to the report data 398 * len - length of report data 399 * mode - Hid host Protocol Mode 400 * sub_clas - Device Subclass 401 * app_id - application id 402 * 403 * Returns void 404 ******************************************************************************/ 405void bta_hh_co_data(uint8_t dev_handle, uint8_t* p_rpt, uint16_t len, 406 tBTA_HH_PROTO_MODE mode, uint8_t sub_class, 407 uint8_t ctry_code, BD_ADDR peer_addr, uint8_t app_id) { 408 btif_hh_device_t* p_dev; 409 UNUSED(peer_addr); 410 411 APPL_TRACE_DEBUG( 412 "%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " 413 "ctry_code = %d, app_id = %d", 414 __func__, dev_handle, sub_class, mode, ctry_code, app_id); 415 416 p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); 417 if (p_dev == NULL) { 418 APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __func__, 419 dev_handle); 420 return; 421 } 422 423 // Wait a maximum of MAX_POLLING_ATTEMPTS x POLLING_SLEEP_DURATION in case 424 // device creation is pending. 425 if (p_dev->fd >= 0) { 426 uint32_t polling_attempts = 0; 427 while (!p_dev->ready_for_data && 428 polling_attempts++ < BTIF_HH_MAX_POLLING_ATTEMPTS) { 429 usleep(BTIF_HH_POLLING_SLEEP_DURATION_US); 430 } 431 } 432 433 // Send the HID data to the kernel. 434 if ((p_dev->fd >= 0) && p_dev->ready_for_data) { 435 bta_hh_co_write(p_dev->fd, p_rpt, len); 436 } else { 437 APPL_TRACE_WARNING("%s: Error: fd = %d, ready %d, len = %d", __func__, 438 p_dev->fd, p_dev->ready_for_data, len); 439 } 440} 441 442/******************************************************************************* 443 * 444 * Function bta_hh_co_send_hid_info 445 * 446 * Description This function is called in btif_hh.c to process DSCP 447 *received. 448 * 449 * Parameters dev_handle - device handle 450 * dscp_len - report descriptor length 451 * *p_dscp - report descriptor 452 * 453 * Returns void 454 ******************************************************************************/ 455void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, 456 uint16_t vendor_id, uint16_t product_id, 457 uint16_t version, uint8_t ctry_code, int dscp_len, 458 uint8_t* p_dscp) { 459 int result; 460 struct uhid_event ev; 461 462 if (p_dev->fd < 0) { 463 APPL_TRACE_WARNING("%s: Error: fd = %d, dscp_len = %d", __func__, p_dev->fd, 464 dscp_len); 465 return; 466 } 467 468 APPL_TRACE_WARNING("%s: fd = %d, name = [%s], dscp_len = %d", __func__, 469 p_dev->fd, dev_name, dscp_len); 470 APPL_TRACE_WARNING( 471 "%s: vendor_id = 0x%04x, product_id = 0x%04x, version= 0x%04x," 472 "ctry_code=0x%02x", 473 __func__, vendor_id, product_id, version, ctry_code); 474 475 // Create and send hid descriptor to kernel 476 memset(&ev, 0, sizeof(ev)); 477 ev.type = UHID_CREATE; 478 strncpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name) - 1); 479 snprintf((char*)ev.u.create.uniq, sizeof(ev.u.create.uniq), 480 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", p_dev->bd_addr.address[5], 481 p_dev->bd_addr.address[4], p_dev->bd_addr.address[3], 482 p_dev->bd_addr.address[2], p_dev->bd_addr.address[1], 483 p_dev->bd_addr.address[0]); 484 ev.u.create.rd_size = dscp_len; 485 ev.u.create.rd_data = p_dscp; 486 ev.u.create.bus = BUS_BLUETOOTH; 487 ev.u.create.vendor = vendor_id; 488 ev.u.create.product = product_id; 489 ev.u.create.version = version; 490 ev.u.create.country = ctry_code; 491 result = uhid_write(p_dev->fd, &ev); 492 493 APPL_TRACE_WARNING( 494 "%s: wrote descriptor to fd = %d, dscp_len = %d, result = %d", __func__, 495 p_dev->fd, dscp_len, result); 496 497 if (result) { 498 APPL_TRACE_WARNING("%s: Error: failed to send DSCP, result = %d", __func__, 499 result); 500 501 /* The HID report descriptor is corrupted. Close the driver. */ 502 close(p_dev->fd); 503 p_dev->fd = -1; 504 } 505} 506 507#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) 508/******************************************************************************* 509 * 510 * Function bta_hh_le_co_rpt_info 511 * 512 * Description This callout function is to convey the report information on 513 * a HOGP device to the application. Application can save this 514 * information in NV if device is bonded and load it back when 515 * stack reboot. 516 * 517 * Parameters remote_bda - remote device address 518 * p_entry - report entry pointer 519 * app_id - application id 520 * 521 * Returns void. 522 * 523 ******************************************************************************/ 524void bta_hh_le_co_rpt_info(BD_ADDR remote_bda, tBTA_HH_RPT_CACHE_ENTRY* p_entry, 525 uint8_t app_id) { 526 UNUSED(app_id); 527 528 unsigned idx = 0; 529 530 bdstr_t bdstr; 531 snprintf(bdstr, sizeof(bdstr), "%02x:%02x:%02x:%02x:%02x:%02x", remote_bda[0], 532 remote_bda[1], remote_bda[2], remote_bda[3], remote_bda[4], 533 remote_bda[5]); 534 535 size_t len = btif_config_get_bin_length(bdstr, "HidReport"); 536 if (len >= sizeof(tBTA_HH_RPT_CACHE_ENTRY) && len <= sizeof(sReportCache)) { 537 btif_config_get_bin(bdstr, "HidReport", (uint8_t*)sReportCache, &len); 538 idx = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY); 539 } 540 541 if (idx < BTA_HH_NV_LOAD_MAX) { 542 memcpy(&sReportCache[idx++], p_entry, sizeof(tBTA_HH_RPT_CACHE_ENTRY)); 543 btif_config_set_bin(bdstr, "HidReport", (const uint8_t*)sReportCache, 544 idx * sizeof(tBTA_HH_RPT_CACHE_ENTRY)); 545 BTIF_TRACE_DEBUG("%s() - Saving report; dev=%s, idx=%d", __func__, bdstr, 546 idx); 547 } 548} 549 550/******************************************************************************* 551 * 552 * Function bta_hh_le_co_cache_load 553 * 554 * Description This callout function is to request the application to load 555 *the 556 * cached HOGP report if there is any. When cache reading is 557 *completed, 558 * bta_hh_le_ci_cache_load() is called by the application. 559 * 560 * Parameters remote_bda - remote device address 561 * p_num_rpt: number of cached report 562 * app_id - application id 563 * 564 * Returns the acched report array 565 * 566 ******************************************************************************/ 567tBTA_HH_RPT_CACHE_ENTRY* bta_hh_le_co_cache_load(BD_ADDR remote_bda, 568 uint8_t* p_num_rpt, 569 uint8_t app_id) { 570 UNUSED(app_id); 571 572 bdstr_t bdstr; 573 snprintf(bdstr, sizeof(bdstr), "%02x:%02x:%02x:%02x:%02x:%02x", remote_bda[0], 574 remote_bda[1], remote_bda[2], remote_bda[3], remote_bda[4], 575 remote_bda[5]); 576 577 size_t len = btif_config_get_bin_length(bdstr, "HidReport"); 578 if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) return NULL; 579 580 if (len > sizeof(sReportCache)) len = sizeof(sReportCache); 581 btif_config_get_bin(bdstr, "HidReport", (uint8_t*)sReportCache, &len); 582 *p_num_rpt = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY); 583 584 BTIF_TRACE_DEBUG("%s() - Loaded %d reports; dev=%s", __func__, *p_num_rpt, 585 bdstr); 586 587 return sReportCache; 588} 589 590/******************************************************************************* 591 * 592 * Function bta_hh_le_co_reset_rpt_cache 593 * 594 * Description This callout function is to reset the HOGP device cache. 595 * 596 * Parameters remote_bda - remote device address 597 * 598 * Returns none 599 * 600 ******************************************************************************/ 601void bta_hh_le_co_reset_rpt_cache(BD_ADDR remote_bda, uint8_t app_id) { 602 UNUSED(app_id); 603 604 bdstr_t bdstr; 605 snprintf(bdstr, sizeof(bdstr), "%02x:%02x:%02x:%02x:%02x:%02x", remote_bda[0], 606 remote_bda[1], remote_bda[2], remote_bda[3], remote_bda[4], 607 remote_bda[5]); 608 btif_config_remove(bdstr, "HidReport"); 609 610 BTIF_TRACE_DEBUG("%s() - Reset cache for bda %s", __func__, bdstr); 611} 612 613#endif // (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) 614