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