Home | History | Annotate | Download | only in hh
      1 /******************************************************************************
      2  *
      3  *  Copyright 2009-2013 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 #define LOG_TAG "bt_bta_hh"
     20 
     21 #include "bta_api.h"
     22 #include "bta_hh_int.h"
     23 #include "osi/include/osi.h"
     24 
     25 #if (BTA_HH_LE_INCLUDED == TRUE)
     26 
     27 #include <string.h>
     28 
     29 #include <base/bind.h>
     30 #include <base/callback.h>
     31 
     32 #include "bta_gatt_api.h"
     33 #include "bta_gatt_queue.h"
     34 #include "bta_hh_co.h"
     35 #include "btm_api.h"
     36 #include "btm_ble_api.h"
     37 #include "btm_int.h"
     38 #include "device/include/interop.h"
     39 #include "osi/include/log.h"
     40 #include "srvc_api.h"
     41 #include "stack/include/l2c_api.h"
     42 #include "utl.h"
     43 
     44 using bluetooth::Uuid;
     45 using std::vector;
     46 
     47 #ifndef BTA_HH_LE_RECONN
     48 #define BTA_HH_LE_RECONN TRUE
     49 #endif
     50 
     51 #define BTA_HH_APP_ID_LE 0xff
     52 
     53 #define BTA_HH_LE_RPT_TYPE_VALID(x) \
     54   ((x) <= BTA_LE_HID_RPT_FEATURE && (x) >= BTA_LE_HID_RPT_INPUT)
     55 
     56 #define BTA_HH_LE_PROTO_BOOT_MODE 0x00
     57 #define BTA_HH_LE_PROTO_REPORT_MODE 0x01
     58 
     59 #define BTA_LE_HID_RTP_UUID_MAX 5
     60 static const uint16_t bta_hh_uuid_to_rtp_type[BTA_LE_HID_RTP_UUID_MAX][2] = {
     61     {GATT_UUID_HID_REPORT, BTA_HH_RPTT_INPUT},
     62     {GATT_UUID_HID_BT_KB_INPUT, BTA_HH_RPTT_INPUT},
     63     {GATT_UUID_HID_BT_KB_OUTPUT, BTA_HH_RPTT_OUTPUT},
     64     {GATT_UUID_HID_BT_MOUSE_INPUT, BTA_HH_RPTT_INPUT},
     65     {GATT_UUID_BATTERY_LEVEL, BTA_HH_RPTT_INPUT}};
     66 
     67 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
     68 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB* p_cb, bool check_bond);
     69 // TODO(jpawlowski): uncomment when fixed
     70 // static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
     71 //                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
     72 //                                       uint8_t num_rpt);
     73 
     74 #if (BTA_HH_DEBUG == TRUE)
     75 static const char* bta_hh_le_rpt_name[4] = {"UNKNOWN", "INPUT", "OUTPUT",
     76                                             "FEATURE"};
     77 
     78 /*******************************************************************************
     79  *
     80  * Function         bta_hh_le_hid_report_dbg
     81  *
     82  * Description      debug function to print out all HID report available on
     83  *                  remote device.
     84  *
     85  * Returns          void
     86  *
     87  ******************************************************************************/
     88 static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB* p_cb) {
     89   APPL_TRACE_DEBUG("%s: HID Report DB", __func__);
     90 
     91   if (!p_cb->hid_srvc.in_use) return;
     92 
     93   tBTA_HH_LE_RPT* p_rpt = &p_cb->hid_srvc.report[0];
     94 
     95   for (int j = 0; j < BTA_HH_LE_RPT_MAX; j++, p_rpt++) {
     96     const char* rpt_name = "Unknown";
     97 
     98     if (!p_rpt->in_use) break;
     99 
    100     if (p_rpt->uuid == GATT_UUID_HID_REPORT) rpt_name = "Report";
    101     if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT) rpt_name = "Boot KB Input";
    102     if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT) rpt_name = "Boot KB Output";
    103     if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) rpt_name = "Boot MI Input";
    104 
    105     APPL_TRACE_DEBUG(
    106         "\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [srvc_inst_id: %d] "
    107         "[char_inst_id: %d] [Clt_cfg: %d]",
    108         rpt_name, p_rpt->uuid,
    109         ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type]
    110                                : "UNKNOWN"),
    111         p_rpt->rpt_id, p_rpt->srvc_inst_id, p_rpt->char_inst_id,
    112         p_rpt->client_cfg_value);
    113   }
    114 }
    115 
    116 /*******************************************************************************
    117  *
    118  * Function         bta_hh_uuid_to_str
    119  *
    120  * Description
    121  *
    122  * Returns          void
    123  *
    124  ******************************************************************************/
    125 static const char* bta_hh_uuid_to_str(uint16_t uuid) {
    126   switch (uuid) {
    127     case GATT_UUID_HID_INFORMATION:
    128       return "GATT_UUID_HID_INFORMATION";
    129     case GATT_UUID_HID_REPORT_MAP:
    130       return "GATT_UUID_HID_REPORT_MAP";
    131     case GATT_UUID_HID_CONTROL_POINT:
    132       return "GATT_UUID_HID_CONTROL_POINT";
    133     case GATT_UUID_HID_REPORT:
    134       return "GATT_UUID_HID_REPORT";
    135     case GATT_UUID_HID_PROTO_MODE:
    136       return "GATT_UUID_HID_PROTO_MODE";
    137     case GATT_UUID_HID_BT_KB_INPUT:
    138       return "GATT_UUID_HID_BT_KB_INPUT";
    139     case GATT_UUID_HID_BT_KB_OUTPUT:
    140       return "GATT_UUID_HID_BT_KB_OUTPUT";
    141     case GATT_UUID_HID_BT_MOUSE_INPUT:
    142       return "GATT_UUID_HID_BT_MOUSE_INPUT";
    143     case GATT_UUID_CHAR_CLIENT_CONFIG:
    144       return "GATT_UUID_CHAR_CLIENT_CONFIG";
    145     case GATT_UUID_EXT_RPT_REF_DESCR:
    146       return "GATT_UUID_EXT_RPT_REF_DESCR";
    147     case GATT_UUID_RPT_REF_DESCR:
    148       return "GATT_UUID_RPT_REF_DESCR";
    149     default:
    150       return "Unknown UUID";
    151   }
    152 }
    153 
    154 #endif
    155 /*******************************************************************************
    156  *
    157  * Function         bta_hh_le_enable
    158  *
    159  * Description      initialize LE HID related functionality
    160  *
    161  *
    162  * Returns          void
    163  *
    164  ******************************************************************************/
    165 void bta_hh_le_enable(void) {
    166   uint8_t xx;
    167 
    168   bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
    169 
    170   for (xx = 0; xx < ARRAY_SIZE(bta_hh_cb.le_cb_index); xx++)
    171     bta_hh_cb.le_cb_index[xx] = BTA_HH_IDX_INVALID;
    172 
    173   BTA_GATTC_AppRegister(bta_hh_gattc_callback,
    174                         base::Bind([](uint8_t client_id, uint8_t r_status) {
    175                           tBTA_HH bta_hh;
    176                           bta_hh.status = BTA_HH_ERR;
    177 
    178                           if (r_status == GATT_SUCCESS) {
    179                             bta_hh_cb.gatt_if = client_id;
    180                             bta_hh.status = BTA_HH_OK;
    181                           } else {
    182                             bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
    183                           }
    184 
    185                           /* null check is needed in case HID profile is shut
    186                            * down before BTA_GATTC_AppRegister is done */
    187                           if (bta_hh_cb.p_cback) {
    188                             /* signal BTA call back event */
    189                             (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, &bta_hh);
    190                           }
    191                         }));
    192 }
    193 
    194 /*******************************************************************************
    195  *
    196  * Function         bta_hh_le_is_hh_gatt_if
    197  *
    198  * Description      Check to see if client_if is BTA HH LE GATT interface
    199  *
    200  *
    201  * Returns          whether it is HH GATT IF
    202  *
    203  ******************************************************************************/
    204 bool bta_hh_le_is_hh_gatt_if(tGATT_IF client_if) {
    205   return (bta_hh_cb.gatt_if == client_if);
    206 }
    207 
    208 /*******************************************************************************
    209  *
    210  * Function         bta_hh_le_deregister
    211  *
    212  * Description      De-register BTA HH from BTA GATTC
    213  *
    214  *
    215  * Returns          void
    216  *
    217  ******************************************************************************/
    218 void bta_hh_le_deregister(void) { BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if); }
    219 
    220 /*******************************************************************************
    221  *
    222  * Function         bta_hh_is_le_device
    223  *
    224  * Description      Check to see if the remote device is a LE only device
    225  *
    226  * Parameters:
    227  *
    228  ******************************************************************************/
    229 bool bta_hh_is_le_device(tBTA_HH_DEV_CB* p_cb, const RawAddress& remote_bda) {
    230   p_cb->is_le_device = BTM_UseLeLink(remote_bda);
    231 
    232   return p_cb->is_le_device;
    233 }
    234 
    235 /******************************************************************************
    236  *
    237  * Function         bta_hh_le_get_le_cb
    238  *
    239  * Description      Allocate bta_hh_cb.le_cb_index
    240  *
    241  * Parameters:
    242  *
    243  ******************************************************************************/
    244 uint8_t bta_hh_le_get_le_dev_hdl(uint8_t cb_index) {
    245   uint8_t i;
    246   for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
    247     if (bta_hh_cb.le_cb_index[i] == cb_index) return BTA_HH_GET_LE_DEV_HDL(i);
    248   }
    249 
    250   for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
    251     if (bta_hh_cb.le_cb_index[i] == BTA_HH_IDX_INVALID)
    252       return BTA_HH_GET_LE_DEV_HDL(i);
    253   }
    254   return BTA_HH_IDX_INVALID;
    255 }
    256 
    257 /*******************************************************************************
    258  *
    259  * Function         bta_hh_le_open_conn
    260  *
    261  * Description      open a GATT connection first.
    262  *
    263  * Parameters:
    264  *
    265  ******************************************************************************/
    266 void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb, const RawAddress& remote_bda) {
    267   tBTA_HH_STATUS status = BTA_HH_ERR_NO_RES;
    268 
    269   /* update cb_index[] map */
    270   p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
    271   if (p_cb->hid_handle == BTA_HH_IDX_INVALID) {
    272     bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
    273     return;
    274   }
    275 
    276   p_cb->addr = remote_bda;
    277   bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
    278   p_cb->in_use = true;
    279 
    280   BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, true, GATT_TRANSPORT_LE, false);
    281 }
    282 
    283 /*******************************************************************************
    284  *
    285  * Function         bta_hh_le_find_dev_cb_by_conn_id
    286  *
    287  * Description      Utility function find a device control block by connection
    288  *                  ID.
    289  *
    290  ******************************************************************************/
    291 tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_conn_id(uint16_t conn_id) {
    292   uint8_t i;
    293   tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[0];
    294 
    295   for (i = 0; i < BTA_HH_MAX_DEVICE; i++, p_dev_cb++) {
    296     if (p_dev_cb->in_use && p_dev_cb->conn_id == conn_id) return p_dev_cb;
    297   }
    298   return NULL;
    299 }
    300 
    301 /*******************************************************************************
    302  *
    303  * Function         bta_hh_le_find_dev_cb_by_bda
    304  *
    305  * Description      Utility function find a device control block by BD address.
    306  *
    307  ******************************************************************************/
    308 tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_bda(const RawAddress& bda) {
    309   uint8_t i;
    310   tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[0];
    311 
    312   for (i = 0; i < BTA_HH_MAX_DEVICE; i++, p_dev_cb++) {
    313     if (p_dev_cb->in_use && p_dev_cb->addr == bda) return p_dev_cb;
    314   }
    315   return NULL;
    316 }
    317 
    318 /*******************************************************************************
    319  *
    320  * Function         bta_hh_le_find_service_inst_by_battery_inst_id
    321  *
    322  * Description      find HID service instance ID by battery service instance ID
    323  *
    324  ******************************************************************************/
    325 uint8_t bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB* p_cb,
    326                                                        uint8_t ba_inst_id) {
    327   if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.incl_srvc_inst == ba_inst_id) {
    328     return p_cb->hid_srvc.srvc_inst_id;
    329   }
    330   return BTA_HH_IDX_INVALID;
    331 }
    332 
    333 /*******************************************************************************
    334  *
    335  * Function         bta_hh_le_find_report_entry
    336  *
    337  * Description      find the report entry by service instance and report UUID
    338  *                  and instance ID
    339  *
    340  ******************************************************************************/
    341 tBTA_HH_LE_RPT* bta_hh_le_find_report_entry(
    342     tBTA_HH_DEV_CB* p_cb, uint8_t srvc_inst_id, /* service instance ID */
    343     uint16_t rpt_uuid, uint8_t char_inst_id) {
    344   uint8_t i;
    345   uint8_t hid_inst_id = srvc_inst_id;
    346   tBTA_HH_LE_RPT* p_rpt;
    347 
    348   if (rpt_uuid == GATT_UUID_BATTERY_LEVEL) {
    349     hid_inst_id =
    350         bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
    351 
    352     if (hid_inst_id == BTA_HH_IDX_INVALID) return NULL;
    353   }
    354 
    355   p_rpt = &p_cb->hid_srvc.report[0];
    356 
    357   for (i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
    358     if (p_rpt->uuid == rpt_uuid && p_rpt->srvc_inst_id == srvc_inst_id &&
    359         p_rpt->char_inst_id == char_inst_id) {
    360       return p_rpt;
    361     }
    362   }
    363   return NULL;
    364 }
    365 
    366 /*******************************************************************************
    367  *
    368  * Function         bta_hh_le_find_rpt_by_idtype
    369  *
    370  * Description      find a report entry by report ID and protocol mode
    371  *
    372  * Returns          void
    373  *
    374  ******************************************************************************/
    375 tBTA_HH_LE_RPT* bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT* p_head,
    376                                              uint8_t mode,
    377                                              tBTA_HH_RPT_TYPE r_type,
    378                                              uint8_t rpt_id) {
    379   tBTA_HH_LE_RPT* p_rpt = p_head;
    380   uint8_t i;
    381 
    382 #if (BTA_HH_DEBUG == TRUE)
    383   APPL_TRACE_DEBUG("bta_hh_le_find_rpt_by_idtype: r_type: %d rpt_id: %d",
    384                    r_type, rpt_id);
    385 #endif
    386 
    387   for (i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
    388     if (p_rpt->in_use && p_rpt->rpt_id == rpt_id && r_type == p_rpt->rpt_type) {
    389       /* return battery report w/o condition */
    390       if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) return p_rpt;
    391 
    392       if (mode == BTA_HH_PROTO_RPT_MODE && p_rpt->uuid == GATT_UUID_HID_REPORT)
    393         return p_rpt;
    394 
    395       if (mode == BTA_HH_PROTO_BOOT_MODE &&
    396           (p_rpt->uuid >= GATT_UUID_HID_BT_KB_INPUT &&
    397            p_rpt->uuid <= GATT_UUID_HID_BT_MOUSE_INPUT))
    398         return p_rpt;
    399     }
    400   }
    401   return NULL;
    402 }
    403 
    404 /*******************************************************************************
    405  *
    406  * Function         bta_hh_le_find_alloc_report_entry
    407  *
    408  * Description      find or allocate a report entry in the HID service report
    409  *                  list.
    410  *
    411  ******************************************************************************/
    412 tBTA_HH_LE_RPT* bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB* p_cb,
    413                                                   uint8_t srvc_inst_id,
    414                                                   uint16_t rpt_uuid,
    415                                                   uint8_t inst_id) {
    416   uint8_t i, hid_inst_id = srvc_inst_id;
    417   tBTA_HH_LE_RPT* p_rpt;
    418 
    419   if (rpt_uuid == GATT_UUID_BATTERY_LEVEL) {
    420     hid_inst_id =
    421         bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
    422 
    423     if (hid_inst_id == BTA_HH_IDX_INVALID) return NULL;
    424   }
    425   p_rpt = &p_cb->hid_srvc.report[0];
    426 
    427   for (i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
    428     if (!p_rpt->in_use ||
    429         (p_rpt->uuid == rpt_uuid && p_rpt->srvc_inst_id == srvc_inst_id &&
    430          p_rpt->char_inst_id == inst_id)) {
    431       if (!p_rpt->in_use) {
    432         p_rpt->in_use = true;
    433         p_rpt->index = i;
    434         p_rpt->srvc_inst_id = srvc_inst_id;
    435         p_rpt->char_inst_id = inst_id;
    436         p_rpt->uuid = rpt_uuid;
    437 
    438         /* assign report type */
    439         for (i = 0; i < BTA_LE_HID_RTP_UUID_MAX; i++) {
    440           if (bta_hh_uuid_to_rtp_type[i][0] == rpt_uuid) {
    441             p_rpt->rpt_type = (tBTA_HH_RPT_TYPE)bta_hh_uuid_to_rtp_type[i][1];
    442 
    443             if (rpt_uuid == GATT_UUID_HID_BT_KB_INPUT ||
    444                 rpt_uuid == GATT_UUID_HID_BT_KB_OUTPUT)
    445               p_rpt->rpt_id = BTA_HH_KEYBD_RPT_ID;
    446 
    447             if (rpt_uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
    448               p_rpt->rpt_id = BTA_HH_MOUSE_RPT_ID;
    449 
    450             break;
    451           }
    452         }
    453       }
    454       return p_rpt;
    455     }
    456   }
    457   return NULL;
    458 }
    459 
    460 static const tBTA_GATTC_DESCRIPTOR* find_descriptor_by_short_uuid(
    461     uint16_t conn_id, uint16_t char_handle, uint16_t short_uuid) {
    462   const tBTA_GATTC_CHARACTERISTIC* p_char =
    463       BTA_GATTC_GetCharacteristic(conn_id, char_handle);
    464 
    465   if (!p_char) {
    466     LOG_WARN(LOG_TAG, "%s No such characteristic: %d", __func__, char_handle);
    467     return NULL;
    468   }
    469 
    470   for (const tBTA_GATTC_DESCRIPTOR& desc : p_char->descriptors) {
    471     if (desc.uuid == Uuid::From16Bit(short_uuid)) return &desc;
    472   }
    473 
    474   return NULL;
    475 }
    476 
    477 /*******************************************************************************
    478  *
    479  * Function         bta_hh_le_read_char_descriptor
    480  *
    481  * Description      read characteristic descriptor
    482  *
    483  ******************************************************************************/
    484 static tBTA_HH_STATUS bta_hh_le_read_char_descriptor(tBTA_HH_DEV_CB* p_cb,
    485                                                      uint16_t char_handle,
    486                                                      uint16_t short_uuid,
    487                                                      GATT_READ_OP_CB cb,
    488                                                      void* cb_data) {
    489   const tBTA_GATTC_DESCRIPTOR* p_desc =
    490       find_descriptor_by_short_uuid(p_cb->conn_id, char_handle, short_uuid);
    491   if (!p_desc) return BTA_HH_ERR;
    492 
    493   BtaGattQueue::ReadDescriptor(p_cb->conn_id, p_desc->handle, cb, cb_data);
    494   return BTA_HH_OK;
    495 }
    496 
    497 /*******************************************************************************
    498  *
    499  * Function         bta_hh_le_save_report_ref
    500  *
    501  * Description      save report reference information and move to next one.
    502  *
    503  * Parameters:
    504  *
    505  ******************************************************************************/
    506 void bta_hh_le_save_report_ref(tBTA_HH_DEV_CB* p_dev_cb, tBTA_HH_LE_RPT* p_rpt,
    507                                tGATT_STATUS status, uint8_t* value,
    508                                uint16_t len) {
    509   if (status == GATT_INSUF_AUTHENTICATION) {
    510     /* close connection right away */
    511     p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
    512     /* close the connection and report service discovery complete with error */
    513     bta_hh_le_api_disc_act(p_dev_cb);
    514     return;
    515   }
    516 
    517   /* if the length of the descriptor value is right, parse it */
    518   if (status == GATT_SUCCESS && len == 2) {
    519     uint8_t* pp = value;
    520 
    521     STREAM_TO_UINT8(p_rpt->rpt_id, pp);
    522     STREAM_TO_UINT8(p_rpt->rpt_type, pp);
    523 
    524     if (p_rpt->rpt_type > BTA_HH_RPTT_FEATURE) /* invalid report type */
    525       p_rpt->rpt_type = BTA_HH_RPTT_RESRV;
    526 
    527 #if (BTA_HH_DEBUG == TRUE)
    528     APPL_TRACE_DEBUG("%s: report ID: %d", __func__, p_rpt->rpt_id);
    529 #endif
    530     tBTA_HH_RPT_CACHE_ENTRY rpt_entry;
    531     rpt_entry.rpt_id = p_rpt->rpt_id;
    532     rpt_entry.rpt_type = p_rpt->rpt_type;
    533     rpt_entry.rpt_uuid = p_rpt->uuid;
    534     rpt_entry.srvc_inst_id = p_rpt->srvc_inst_id;
    535     rpt_entry.char_inst_id = p_rpt->char_inst_id;
    536 
    537     bta_hh_le_co_rpt_info(p_dev_cb->addr, &rpt_entry, p_dev_cb->app_id);
    538   }
    539 
    540   if (p_rpt->index < BTA_HH_LE_RPT_MAX - 1)
    541     p_rpt++;
    542   else
    543     p_rpt = NULL;
    544 }
    545 
    546 /*******************************************************************************
    547  *
    548  * Function         bta_hh_le_register_input_notif
    549  *
    550  * Description      Register for all notifications for the report applicable
    551  *                  for the protocol mode.
    552  *
    553  * Parameters:
    554  *
    555  ******************************************************************************/
    556 void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB* p_dev_cb,
    557                                     uint8_t proto_mode, bool register_ba) {
    558   tBTA_HH_LE_RPT* p_rpt = &p_dev_cb->hid_srvc.report[0];
    559 
    560 #if (BTA_HH_DEBUG == TRUE)
    561   APPL_TRACE_DEBUG("%s: bta_hh_le_register_input_notif mode: %d", __func__,
    562                    proto_mode);
    563 #endif
    564 
    565   for (int i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
    566     if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
    567       if (register_ba && p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
    568         BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
    569                                            p_rpt->char_inst_id);
    570       }
    571       /* boot mode, deregister report input notification */
    572       else if (proto_mode == BTA_HH_PROTO_BOOT_MODE) {
    573         if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
    574             p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
    575           APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__,
    576                            p_rpt->rpt_id);
    577           BTA_GATTC_DeregisterForNotifications(
    578               bta_hh_cb.gatt_if, p_dev_cb->addr, p_rpt->char_inst_id);
    579         }
    580         /* register boot reports notification */
    581         else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
    582                  p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) {
    583           APPL_TRACE_DEBUG("%s <--- Register Boot Report ID: %d", __func__,
    584                            p_rpt->rpt_id);
    585           BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
    586                                              p_rpt->char_inst_id);
    587         }
    588       } else if (proto_mode == BTA_HH_PROTO_RPT_MODE) {
    589         if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
    590              p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
    591             p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
    592           APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__,
    593                            p_rpt->rpt_id);
    594           BTA_GATTC_DeregisterForNotifications(
    595               bta_hh_cb.gatt_if, p_dev_cb->addr, p_rpt->char_inst_id);
    596         } else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
    597                    p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
    598           APPL_TRACE_DEBUG("%s <--- Register Report ID: %d", __func__,
    599                            p_rpt->rpt_id);
    600           BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
    601                                              p_rpt->char_inst_id);
    602         }
    603       }
    604       /*
    605       else unknow protocol mode */
    606     }
    607   }
    608 }
    609 
    610 /*******************************************************************************
    611  *
    612  * Function         bta_hh_le_deregister_input_notif
    613  *
    614  * Description      Deregister all notifications
    615  *
    616  ******************************************************************************/
    617 void bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB* p_dev_cb) {
    618   tBTA_HH_LE_RPT* p_rpt = &p_dev_cb->hid_srvc.report[0];
    619 
    620   for (uint8_t i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
    621     if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
    622       if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
    623           p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
    624         APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__,
    625                          p_rpt->rpt_id);
    626         BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
    627                                              p_rpt->char_inst_id);
    628       } else if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
    629                   p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
    630                  p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
    631         APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__,
    632                          p_rpt->rpt_id);
    633         BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
    634                                              p_rpt->char_inst_id);
    635       }
    636     }
    637   }
    638 }
    639 
    640 /*******************************************************************************
    641  *
    642  * Function         bta_hh_le_open_cmpl
    643  *
    644  * Description      HID over GATT connection sucessfully opened
    645  *
    646  ******************************************************************************/
    647 void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB* p_cb) {
    648   if (p_cb->disc_active == BTA_HH_LE_DISC_NONE) {
    649 #if (BTA_HH_DEBUG == TRUE)
    650     bta_hh_le_hid_report_dbg(p_cb);
    651 #endif
    652     bta_hh_le_register_input_notif(p_cb, p_cb->mode, true);
    653     bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
    654 
    655 #if (BTA_HH_LE_RECONN == TRUE)
    656     if (p_cb->status == BTA_HH_OK) {
    657       bta_hh_le_add_dev_bg_conn(p_cb, true);
    658     }
    659 #endif
    660   }
    661 }
    662 
    663 /*******************************************************************************
    664  *
    665  * Function         bta_hh_le_write_ccc
    666  *
    667  * Description      Utility function to find and write client configuration of
    668  *                  a characteristic
    669  *
    670  ******************************************************************************/
    671 bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint8_t char_handle,
    672                          uint16_t clt_cfg_value, GATT_WRITE_OP_CB cb,
    673                          void* cb_data) {
    674   const tBTA_GATTC_DESCRIPTOR* p_desc = find_descriptor_by_short_uuid(
    675       p_cb->conn_id, char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
    676   if (!p_desc) return false;
    677 
    678   vector<uint8_t> value(2);
    679   uint8_t* ptr = value.data();
    680   UINT16_TO_STREAM(ptr, clt_cfg_value);
    681 
    682   BtaGattQueue::WriteDescriptor(p_cb->conn_id, p_desc->handle, std::move(value),
    683                                 GATT_WRITE, cb, cb_data);
    684   return true;
    685 }
    686 
    687 bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb);
    688 
    689 static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
    690                                  uint16_t handle, void* data) {
    691   uint8_t srvc_inst_id, hid_inst_id;
    692 
    693   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
    694   const tBTA_GATTC_CHARACTERISTIC* characteristic =
    695       BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
    696   uint16_t char_uuid = characteristic->uuid.As16Bit();
    697 
    698   srvc_inst_id = BTA_GATTC_GetOwningService(conn_id, handle)->handle;
    699   hid_inst_id = srvc_inst_id;
    700   switch (char_uuid) {
    701     case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
    702       hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(
    703           p_dev_cb, srvc_inst_id);
    704     /* FALLTHROUGH */
    705     case GATT_UUID_HID_BT_KB_INPUT:
    706     case GATT_UUID_HID_BT_MOUSE_INPUT:
    707     case GATT_UUID_HID_REPORT:
    708       if (status == GATT_SUCCESS)
    709         p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
    710             GATT_CLT_CONFIG_NOTIFICATION;
    711       p_dev_cb->clt_cfg_idx++;
    712       bta_hh_le_write_rpt_clt_cfg(p_dev_cb);
    713       break;
    714 
    715     default:
    716       APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", char_uuid);
    717   }
    718 }
    719 /*******************************************************************************
    720  *
    721  * Function         bta_hh_le_write_rpt_clt_cfg
    722  *
    723  * Description      write client configuration. This is only for input report
    724  *                  enable all input notification upon connection open.
    725  *
    726  ******************************************************************************/
    727 bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb) {
    728   uint8_t i;
    729   tBTA_HH_LE_RPT* p_rpt = &p_cb->hid_srvc.report[p_cb->clt_cfg_idx];
    730 
    731   for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use;
    732        i++, p_rpt++) {
    733     /* enable notification for all input report, regardless mode */
    734     if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
    735       if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id,
    736                               GATT_CLT_CONFIG_NOTIFICATION,
    737                               write_rpt_ctl_cfg_cb, p_cb)) {
    738         p_cb->clt_cfg_idx = i;
    739         return true;
    740       }
    741     }
    742   }
    743   p_cb->clt_cfg_idx = 0;
    744 
    745   /* client configuration is completed, send open callback */
    746   if (p_cb->state == BTA_HH_W4_CONN_ST) {
    747     p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
    748 
    749     bta_hh_le_open_cmpl(p_cb);
    750   }
    751   return false;
    752 }
    753 
    754 static void write_proto_mode_cb(uint16_t conn_id, tGATT_STATUS status,
    755                                 uint16_t handle, void* data) {
    756   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
    757 
    758   if (p_dev_cb->state == BTA_HH_CONN_ST) {
    759     /* Set protocol finished in CONN state*/
    760 
    761     uint16_t cb_evt = p_dev_cb->w4_evt;
    762     if (cb_evt == 0) return;
    763 
    764     tBTA_HH_CBDATA cback_data;
    765 
    766     cback_data.handle = p_dev_cb->hid_handle;
    767     cback_data.status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR;
    768 
    769     if (status == GATT_SUCCESS)
    770       bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, false);
    771 
    772     p_dev_cb->w4_evt = 0;
    773     (*bta_hh_cb.p_cback)(cb_evt, (tBTA_HH*)&cback_data);
    774   } else if (p_dev_cb->state == BTA_HH_W4_CONN_ST) {
    775     p_dev_cb->status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
    776 
    777     if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) == 0)
    778       bta_hh_le_open_cmpl(p_dev_cb);
    779   }
    780 }
    781 
    782 /*******************************************************************************
    783  *
    784  * Function         bta_hh_le_set_protocol_mode
    785  *
    786  * Description      Set remote device protocol mode.
    787  *
    788  ******************************************************************************/
    789 bool bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB* p_cb,
    790                                  tBTA_HH_PROTO_MODE mode) {
    791   tBTA_HH_CBDATA cback_data;
    792 
    793   APPL_TRACE_DEBUG("%s attempt mode: %s", __func__,
    794                    (mode == BTA_HH_PROTO_RPT_MODE) ? "Report" : "Boot");
    795 
    796   cback_data.handle = p_cb->hid_handle;
    797   /* boot mode is not supported in the remote device */
    798   if (p_cb->hid_srvc.proto_mode_handle == 0) {
    799     p_cb->mode = BTA_HH_PROTO_RPT_MODE;
    800 
    801     if (mode == BTA_HH_PROTO_BOOT_MODE) {
    802       APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
    803       cback_data.status = BTA_HH_ERR;
    804     } else {
    805       /* if set to report mode, need to de-register all input report
    806        * notification */
    807       bta_hh_le_register_input_notif(p_cb, p_cb->mode, false);
    808       cback_data.status = BTA_HH_OK;
    809     }
    810     if (p_cb->state == BTA_HH_W4_CONN_ST) {
    811       p_cb->status =
    812           (cback_data.status == BTA_HH_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
    813     } else
    814       (*bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH*)&cback_data);
    815   } else if (p_cb->mode != mode) {
    816     p_cb->mode = mode;
    817     mode = (mode == BTA_HH_PROTO_BOOT_MODE) ? BTA_HH_LE_PROTO_BOOT_MODE
    818                                             : BTA_HH_LE_PROTO_REPORT_MODE;
    819 
    820     BtaGattQueue::WriteCharacteristic(
    821         p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, {mode},
    822         GATT_WRITE_NO_RSP, write_proto_mode_cb, p_cb);
    823     return true;
    824   }
    825 
    826   return false;
    827 }
    828 
    829 /*******************************************************************************
    830  * Function         get_protocol_mode_cb
    831  *
    832  * Description      Process the Read protocol mode, send GET_PROTO_EVT to
    833  *                  application with the protocol mode.
    834  *
    835  ******************************************************************************/
    836 static void get_protocol_mode_cb(uint16_t conn_id, tGATT_STATUS status,
    837                                  uint16_t handle, uint16_t len, uint8_t* value,
    838                                  void* data) {
    839   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
    840   tBTA_HH_HSDATA hs_data;
    841 
    842   hs_data.status = BTA_HH_ERR;
    843   hs_data.handle = p_dev_cb->hid_handle;
    844   hs_data.rsp_data.proto_mode = p_dev_cb->mode;
    845 
    846   if (status == GATT_SUCCESS && len) {
    847     hs_data.status = BTA_HH_OK;
    848     /* match up BTE/BTA report/boot mode def*/
    849     hs_data.rsp_data.proto_mode = *(value);
    850     /* LE repot mode is the opposite value of BR/EDR report mode, flip it here
    851      */
    852     if (hs_data.rsp_data.proto_mode == 0)
    853       hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
    854     else
    855       hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
    856 
    857     p_dev_cb->mode = hs_data.rsp_data.proto_mode;
    858   }
    859 
    860 #if (BTA_HH_DEBUG == TRUE)
    861   APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
    862                    (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
    863                        ? "Report"
    864                        : "Boot");
    865 #endif
    866 
    867   p_dev_cb->w4_evt = 0;
    868   (*bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH*)&hs_data);
    869 }
    870 
    871 /*******************************************************************************
    872  *
    873  * Function         bta_hh_le_get_protocol_mode
    874  *
    875  * Description      Get remote device protocol mode.
    876  *
    877  ******************************************************************************/
    878 void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB* p_cb) {
    879   tBTA_HH_HSDATA hs_data;
    880   p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
    881 
    882   if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
    883     BtaGattQueue::ReadCharacteristic(p_cb->conn_id,
    884                                      p_cb->hid_srvc.proto_mode_handle,
    885                                      get_protocol_mode_cb, p_cb);
    886     return;
    887   }
    888 
    889   /* no service support protocol_mode, by default report mode */
    890   hs_data.status = BTA_HH_OK;
    891   hs_data.handle = p_cb->hid_handle;
    892   hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
    893   p_cb->w4_evt = 0;
    894   (*bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH*)&hs_data);
    895 }
    896 
    897 /*******************************************************************************
    898  *
    899  * Function         bta_hh_le_dis_cback
    900  *
    901  * Description      DIS read complete callback
    902  *
    903  * Parameters:
    904  *
    905  ******************************************************************************/
    906 void bta_hh_le_dis_cback(const RawAddress& addr, tDIS_VALUE* p_dis_value) {
    907   tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
    908 
    909   if (p_cb == NULL || p_dis_value == NULL) {
    910     APPL_TRACE_ERROR("received unexpected/error DIS callback");
    911     return;
    912   }
    913 
    914   p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
    915   /* plug in the PnP info for this device */
    916   if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT) {
    917 #if (BTA_HH_DEBUG == TRUE)
    918     APPL_TRACE_DEBUG(
    919         "Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
    920         p_dis_value->pnp_id.product_id, p_dis_value->pnp_id.vendor_id,
    921         p_dis_value->pnp_id.product_version);
    922 #endif
    923     p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
    924     p_cb->dscp_info.vendor_id = p_dis_value->pnp_id.vendor_id;
    925     p_cb->dscp_info.version = p_dis_value->pnp_id.product_version;
    926   }
    927   bta_hh_le_open_cmpl(p_cb);
    928 }
    929 
    930 /*******************************************************************************
    931  *
    932  * Function         bta_hh_le_pri_service_discovery
    933  *
    934  * Description      Initialize GATT discovery on the remote LE HID device by
    935  *                  opening a GATT connection first.
    936  *
    937  * Parameters:
    938  *
    939  ******************************************************************************/
    940 void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB* p_cb) {
    941   bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
    942 
    943   p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS | BTA_HH_LE_DISC_DIS);
    944 
    945   /* read DIS info */
    946   if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT)) {
    947     APPL_TRACE_ERROR("read DIS failed");
    948     p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
    949   }
    950 
    951   /* in parallel */
    952   /* start primary service discovery for HID service */
    953   Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
    954   BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
    955   return;
    956 }
    957 
    958 /*******************************************************************************
    959  *
    960  * Function         bta_hh_le_encrypt_cback
    961  *
    962  * Description      link encryption complete callback for bond verification.
    963  *
    964  * Returns          None
    965  *
    966  ******************************************************************************/
    967 void bta_hh_le_encrypt_cback(const RawAddress* bd_addr,
    968                              UNUSED_ATTR tGATT_TRANSPORT transport,
    969                              UNUSED_ATTR void* p_ref_data, tBTM_STATUS result) {
    970   uint8_t idx = bta_hh_find_cb(*bd_addr);
    971   tBTA_HH_DEV_CB* p_dev_cb;
    972 
    973   if (idx != BTA_HH_IDX_INVALID)
    974     p_dev_cb = &bta_hh_cb.kdev[idx];
    975   else {
    976     APPL_TRACE_ERROR("unexpected encryption callback, ignore");
    977     return;
    978   }
    979   p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
    980   p_dev_cb->reason = result;
    981 
    982   bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
    983 }
    984 
    985 /*******************************************************************************
    986  *
    987  * Function         bta_hh_security_cmpl
    988  *
    989  * Description      Security check completed, start the service discovery
    990  *                  if no cache available, otherwise report connection open
    991  *                  completed
    992  *
    993  * Parameters:
    994  *
    995  ******************************************************************************/
    996 void bta_hh_security_cmpl(tBTA_HH_DEV_CB* p_cb,
    997                           UNUSED_ATTR tBTA_HH_DATA* p_buf) {
    998   APPL_TRACE_DEBUG("%s", __func__);
    999   if (p_cb->status == BTA_HH_OK) {
   1000     if (!p_cb->hid_srvc.in_use) {
   1001       APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
   1002 
   1003       /* start loading the cache if not in stack */
   1004       // TODO(jpawlowski): cache storage is broken, fix it
   1005       // tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
   1006       // uint8_t                       num_rpt = 0;
   1007       // if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt,
   1008       // p_cb->app_id)) != NULL)
   1009       // {
   1010       //     bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
   1011       // }
   1012     }
   1013     /*  discovery has been done for HID service */
   1014     if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use) {
   1015       APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
   1016       /* configure protocol mode */
   1017       if (!bta_hh_le_set_protocol_mode(p_cb, p_cb->mode)) {
   1018         bta_hh_le_open_cmpl(p_cb);
   1019       }
   1020     }
   1021     /* start primary service discovery for HID service */
   1022     else {
   1023       APPL_TRACE_DEBUG("%s: Starting service discovery", __func__);
   1024       bta_hh_le_pri_service_discovery(p_cb);
   1025     }
   1026   } else {
   1027     APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
   1028                      __func__, p_cb->status, p_cb->reason);
   1029     if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
   1030       bta_hh_le_api_disc_act(p_cb);
   1031   }
   1032 }
   1033 
   1034 /*******************************************************************************
   1035  *
   1036  * Function         bta_hh_le_notify_enc_cmpl
   1037  *
   1038  * Description      process GATT encryption complete event
   1039  *
   1040  * Returns
   1041  *
   1042  ******************************************************************************/
   1043 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_buf) {
   1044   if (p_cb == NULL || !p_cb->security_pending || p_buf == NULL ||
   1045       p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if) {
   1046     return;
   1047   }
   1048 
   1049   p_cb->security_pending = false;
   1050   bta_hh_start_security(p_cb, NULL);
   1051 }
   1052 
   1053 /*******************************************************************************
   1054  *
   1055  * Function         bta_hh_clear_service_cache
   1056  *
   1057  * Description      clear the service cache
   1058  *
   1059  * Parameters:
   1060  *
   1061  ******************************************************************************/
   1062 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB* p_cb) {
   1063   tBTA_HH_LE_HID_SRVC* p_hid_srvc = &p_cb->hid_srvc;
   1064 
   1065   p_cb->app_id = 0;
   1066   p_cb->dscp_info.descriptor.dsc_list = NULL;
   1067 
   1068   osi_free_and_reset((void**)&p_hid_srvc->rpt_map);
   1069   memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
   1070 }
   1071 
   1072 /*******************************************************************************
   1073  *
   1074  * Function         bta_hh_start_security
   1075  *
   1076  * Description      start the security check of the established connection
   1077  *
   1078  * Parameters:
   1079  *
   1080  ******************************************************************************/
   1081 void bta_hh_start_security(tBTA_HH_DEV_CB* p_cb,
   1082                            UNUSED_ATTR tBTA_HH_DATA* p_buf) {
   1083   uint8_t sec_flag = 0;
   1084   tBTM_SEC_DEV_REC* p_dev_rec;
   1085 
   1086   p_dev_rec = btm_find_dev(p_cb->addr);
   1087   if (p_dev_rec) {
   1088     if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
   1089         p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
   1090       /* if security collision happened, wait for encryption done */
   1091       p_cb->security_pending = true;
   1092       return;
   1093     }
   1094   }
   1095 
   1096   /* verify bond */
   1097   BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   1098 
   1099   /* if link has been encrypted */
   1100   if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) {
   1101     p_cb->status = BTA_HH_OK;
   1102     bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1103   }
   1104   /* if bonded and link not encrypted */
   1105   else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) {
   1106     sec_flag = BTM_BLE_SEC_ENCRYPT;
   1107     p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1108     BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback,
   1109                       NULL, sec_flag);
   1110   }
   1111   /* unbonded device, report security error here */
   1112   else if (p_cb->sec_mask != BTA_SEC_NONE) {
   1113     sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
   1114     p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1115     bta_hh_clear_service_cache(p_cb);
   1116     BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback,
   1117                       NULL, sec_flag);
   1118   }
   1119   /* otherwise let it go through */
   1120   else {
   1121     bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1122   }
   1123 }
   1124 
   1125 /*******************************************************************************
   1126  *
   1127  * Function         bta_hh_gatt_open
   1128  *
   1129  * Description      process GATT open event.
   1130  *
   1131  * Parameters:
   1132  *
   1133  ******************************************************************************/
   1134 void bta_hh_gatt_open(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_buf) {
   1135   tBTA_GATTC_OPEN* p_data = &p_buf->le_open;
   1136   uint8_t* p2;
   1137 
   1138   /* if received invalid callback data , ignore it */
   1139   if (p_cb == NULL || p_data == NULL) return;
   1140 
   1141   p2 = p_data->remote_bda.address;
   1142 
   1143   APPL_TRACE_DEBUG(
   1144       "bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
   1145       ((p2[0]) << 24) + ((p2[1]) << 16) + ((p2[2]) << 8) + (p2[3]),
   1146       ((p2[4]) << 8) + p2[5], p_data->status);
   1147 
   1148   if (p_data->status == GATT_SUCCESS) {
   1149     p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
   1150     if (p_cb->hid_handle == BTA_HH_IDX_INVALID) {
   1151       p_cb->conn_id = p_data->conn_id;
   1152       bta_hh_le_api_disc_act(p_cb);
   1153       return;
   1154     }
   1155     p_cb->is_le_device = true;
   1156     p_cb->in_use = true;
   1157     p_cb->conn_id = p_data->conn_id;
   1158 
   1159     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   1160 
   1161     BtaGattQueue::Clean(p_cb->conn_id);
   1162 
   1163 #if (BTA_HH_DEBUG == TRUE)
   1164     APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d",
   1165                      p_cb->hid_handle, p_cb->conn_id, p_cb->index);
   1166 #endif
   1167 
   1168     bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
   1169 
   1170   } else {
   1171     /* open failure */
   1172     tBTA_HH_DATA bta_hh_data;
   1173     bta_hh_data.status = BTA_HH_ERR;
   1174     bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
   1175   }
   1176 }
   1177 
   1178 /*******************************************************************************
   1179  *
   1180  * Function         bta_hh_le_close
   1181  *
   1182  * Description      This function process the GATT close event and post it as a
   1183  *                  BTA HH internal event
   1184  *
   1185  * Parameters:
   1186  *
   1187  ******************************************************************************/
   1188 void bta_hh_le_close(tBTA_GATTC_CLOSE* p_data) {
   1189   tBTA_HH_DEV_CB* p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
   1190   uint16_t sm_event = BTA_HH_GATT_CLOSE_EVT;
   1191 
   1192   if (p_dev_cb != NULL) {
   1193     tBTA_HH_LE_CLOSE* p_buf =
   1194         (tBTA_HH_LE_CLOSE*)osi_malloc(sizeof(tBTA_HH_LE_CLOSE));
   1195     p_buf->hdr.event = sm_event;
   1196     p_buf->hdr.layer_specific = (uint16_t)p_dev_cb->hid_handle;
   1197     p_buf->conn_id = p_data->conn_id;
   1198     p_buf->reason = p_data->reason;
   1199 
   1200     p_dev_cb->conn_id = GATT_INVALID_CONN_ID;
   1201     p_dev_cb->security_pending = false;
   1202     bta_sys_sendmsg(p_buf);
   1203   }
   1204 }
   1205 
   1206 /*******************************************************************************
   1207  *
   1208  * Function         bta_hh_le_gatt_disc_cmpl
   1209  *
   1210  * Description      Check to see if the remote device is a LE only device
   1211  *
   1212  * Parameters:
   1213  *
   1214  ******************************************************************************/
   1215 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB* p_cb, tBTA_HH_STATUS status) {
   1216   APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
   1217 
   1218   /* if open sucessful or protocol mode not desired, keep the connection open
   1219    * but inform app */
   1220   if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO) {
   1221     /* assign a special APP ID temp, since device type unknown */
   1222     p_cb->app_id = BTA_HH_APP_ID_LE;
   1223 
   1224     /* set report notification configuration */
   1225     p_cb->clt_cfg_idx = 0;
   1226     bta_hh_le_write_rpt_clt_cfg(p_cb);
   1227   } else /* error, close the GATT connection */
   1228   {
   1229     /* close GATT connection if it's on */
   1230     bta_hh_le_api_disc_act(p_cb);
   1231   }
   1232 }
   1233 
   1234 static void read_hid_info_cb(uint16_t conn_id, tGATT_STATUS status,
   1235                              uint16_t handle, uint16_t len, uint8_t* value,
   1236                              void* data) {
   1237   if (status != GATT_SUCCESS) {
   1238     APPL_TRACE_ERROR("%s: error: %d", __func__, status);
   1239     return;
   1240   }
   1241 
   1242   if (len != 4) {
   1243     APPL_TRACE_ERROR("%s: wrong length: %d", __func__, len);
   1244     return;
   1245   }
   1246 
   1247   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1248   uint8_t* pp = value;
   1249   /* save device information */
   1250   STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
   1251   STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
   1252   STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
   1253 }
   1254 
   1255 static void read_hid_report_map_cb(uint16_t conn_id, tGATT_STATUS status,
   1256                                    uint16_t handle, uint16_t len,
   1257                                    uint8_t* value, void* data) {
   1258   if (status != GATT_SUCCESS) {
   1259     APPL_TRACE_ERROR("%s: error reading characteristic: %d", __func__, status);
   1260     return;
   1261   }
   1262 
   1263   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1264   tBTA_HH_LE_HID_SRVC* p_srvc = &p_dev_cb->hid_srvc;
   1265 
   1266   osi_free_and_reset((void**)&p_srvc->rpt_map);
   1267 
   1268   if (len > 0) {
   1269     p_srvc->rpt_map = (uint8_t*)osi_malloc(len);
   1270 
   1271     uint8_t* pp = value;
   1272     STREAM_TO_ARRAY(p_srvc->rpt_map, pp, len);
   1273     p_srvc->descriptor.dl_len = len;
   1274     p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map;
   1275   }
   1276 }
   1277 
   1278 static void read_ext_rpt_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status,
   1279                                      uint16_t handle, uint16_t len,
   1280                                      uint8_t* value, void* data) {
   1281   if (status != GATT_SUCCESS) {
   1282     APPL_TRACE_ERROR("%s: error: %d", __func__, status);
   1283     return;
   1284   }
   1285 
   1286   /* if the length of the descriptor value is right, parse it assume it's a 16
   1287    * bits UUID */
   1288   if (len != Uuid::kNumBytes16) {
   1289     APPL_TRACE_ERROR("%s: we support only 16bit UUID: %d", __func__, len);
   1290     return;
   1291   }
   1292 
   1293   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1294   uint8_t* pp = value;
   1295 
   1296   STREAM_TO_UINT16(p_dev_cb->hid_srvc.ext_rpt_ref, pp);
   1297 
   1298 #if (BTA_HH_DEBUG == TRUE)
   1299   APPL_TRACE_DEBUG("%s: External Report Reference UUID 0x%04x", __func__,
   1300                    p_dev_cb->hid_srvc.ext_rpt_ref);
   1301 #endif
   1302 }
   1303 
   1304 static void read_report_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status,
   1305                                     uint16_t handle, uint16_t len,
   1306                                     uint8_t* value, void* data) {
   1307   if (status != GATT_SUCCESS) {
   1308     APPL_TRACE_ERROR("%s: error: %d", __func__, status);
   1309     return;
   1310   }
   1311 
   1312   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1313   const tBTA_GATTC_DESCRIPTOR* p_desc =
   1314       BTA_GATTC_GetDescriptor(conn_id, handle);
   1315 
   1316   if (!p_desc) {
   1317     APPL_TRACE_ERROR("%s: error: descriptor is null!", __func__);
   1318     return;
   1319   }
   1320 
   1321   const tBTA_GATTC_CHARACTERISTIC* characteristic =
   1322       BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
   1323   const tBTA_GATTC_SERVICE* service =
   1324       BTA_GATTC_GetOwningService(conn_id, characteristic->value_handle);
   1325 
   1326   tBTA_HH_LE_RPT* p_rpt;
   1327   p_rpt = bta_hh_le_find_report_entry(p_dev_cb, service->handle,
   1328                                       GATT_UUID_HID_REPORT,
   1329                                       characteristic->value_handle);
   1330   if (p_rpt) bta_hh_le_save_report_ref(p_dev_cb, p_rpt, status, value, len);
   1331 }
   1332 
   1333 void read_pref_conn_params_cb(uint16_t conn_id, tGATT_STATUS status,
   1334                               uint16_t handle, uint16_t len, uint8_t* value,
   1335                               void* data) {
   1336   if (status != GATT_SUCCESS) {
   1337     APPL_TRACE_ERROR("%s: error: %d", __func__, status);
   1338     return;
   1339   }
   1340 
   1341   if (len != 8) {
   1342     APPL_TRACE_ERROR("%s: we support only 16bit UUID: %d", __func__, len);
   1343     return;
   1344   }
   1345 
   1346   // TODO(jpawlowski): this should be done by GAP profile, remove when GAP is
   1347   // fixed.
   1348   uint8_t* pp = value;
   1349   uint16_t min_interval, max_interval, latency, timeout;
   1350   STREAM_TO_UINT16(min_interval, pp);
   1351   STREAM_TO_UINT16(max_interval, pp);
   1352   STREAM_TO_UINT16(latency, pp);
   1353   STREAM_TO_UINT16(timeout, pp);
   1354 
   1355   // Make sure both min, and max are bigger than 11.25ms, lower values can
   1356   // introduce audio issues if A2DP is also active.
   1357   L2CA_AdjustConnectionIntervals(&min_interval, &max_interval,
   1358                                  BTM_BLE_CONN_INT_MIN_LIMIT);
   1359 
   1360   // If the device has no preferred connection timeout, use the default.
   1361   if (timeout == BTM_BLE_CONN_PARAM_UNDEF) timeout = BTM_BLE_CONN_TIMEOUT_DEF;
   1362 
   1363   if (min_interval < BTM_BLE_CONN_INT_MIN ||
   1364       min_interval > BTM_BLE_CONN_INT_MAX ||
   1365       max_interval < BTM_BLE_CONN_INT_MIN ||
   1366       max_interval > BTM_BLE_CONN_INT_MAX ||
   1367       latency > BTM_BLE_CONN_LATENCY_MAX ||
   1368       timeout < BTM_BLE_CONN_SUP_TOUT_MIN ||
   1369       timeout > BTM_BLE_CONN_SUP_TOUT_MAX || max_interval < min_interval) {
   1370     APPL_TRACE_ERROR(
   1371         "%s: Invalid connection parameters. min=%d, max=%d, latency=%d, "
   1372         "timeout=%d",
   1373         __func__, min_interval, max_interval, latency, timeout);
   1374     return;
   1375   }
   1376 
   1377   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1378 
   1379   if (interop_match_addr(INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S,
   1380                          (RawAddress*)&p_dev_cb->addr)) {
   1381     if (timeout < 300) timeout = 300;
   1382   }
   1383 
   1384   BTM_BleSetPrefConnParams(p_dev_cb->addr, min_interval, max_interval, latency,
   1385                            timeout);
   1386   L2CA_UpdateBleConnParams(p_dev_cb->addr, min_interval, max_interval, latency,
   1387                            timeout);
   1388 }
   1389 
   1390 /*******************************************************************************
   1391  *
   1392  * Function         bta_hh_le_search_hid_chars
   1393  *
   1394  * Description      This function discover all characteristics a service and
   1395  *                  all descriptors available.
   1396  *
   1397  * Parameters:
   1398  *
   1399  ******************************************************************************/
   1400 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB* p_dev_cb,
   1401                                        const tBTA_GATTC_SERVICE* service) {
   1402   tBTA_HH_LE_RPT* p_rpt;
   1403 
   1404   for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
   1405     if (!charac.uuid.Is16Bit()) continue;
   1406 
   1407     uint16_t uuid16 = charac.uuid.As16Bit();
   1408     LOG_DEBUG(LOG_TAG, "%s: %s %s", __func__, bta_hh_uuid_to_str(uuid16),
   1409               charac.uuid.ToString().c_str());
   1410 
   1411     switch (uuid16) {
   1412       case GATT_UUID_HID_CONTROL_POINT:
   1413         p_dev_cb->hid_srvc.control_point_handle = charac.value_handle;
   1414         break;
   1415       case GATT_UUID_HID_INFORMATION:
   1416         /* only one instance per HID service */
   1417         BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle,
   1418                                          read_hid_info_cb, p_dev_cb);
   1419         break;
   1420       case GATT_UUID_HID_REPORT_MAP:
   1421         /* only one instance per HID service */
   1422         BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle,
   1423                                          read_hid_report_map_cb, p_dev_cb);
   1424         /* descriptor is optional */
   1425         bta_hh_le_read_char_descriptor(p_dev_cb, charac.value_handle,
   1426                                        GATT_UUID_EXT_RPT_REF_DESCR,
   1427                                        read_ext_rpt_ref_desc_cb, p_dev_cb);
   1428         break;
   1429 
   1430       case GATT_UUID_HID_REPORT:
   1431         p_rpt = bta_hh_le_find_alloc_report_entry(
   1432             p_dev_cb, p_dev_cb->hid_srvc.srvc_inst_id, GATT_UUID_HID_REPORT,
   1433             charac.value_handle);
   1434         if (p_rpt == NULL) {
   1435           APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
   1436           break;
   1437         }
   1438 
   1439         if (p_rpt->rpt_type != BTA_HH_RPTT_INPUT) break;
   1440 
   1441         bta_hh_le_read_char_descriptor(p_dev_cb, charac.value_handle,
   1442                                        GATT_UUID_RPT_REF_DESCR,
   1443                                        read_report_ref_desc_cb, p_dev_cb);
   1444         break;
   1445 
   1446       /* found boot mode report types */
   1447       case GATT_UUID_HID_BT_KB_OUTPUT:
   1448       case GATT_UUID_HID_BT_MOUSE_INPUT:
   1449       case GATT_UUID_HID_BT_KB_INPUT:
   1450         if (bta_hh_le_find_alloc_report_entry(p_dev_cb, service->handle, uuid16,
   1451                                               charac.value_handle) == NULL)
   1452           APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
   1453 
   1454         break;
   1455 
   1456       default:
   1457         APPL_TRACE_DEBUG("%s: not processing %s 0x%04d", __func__,
   1458                          bta_hh_uuid_to_str(uuid16), uuid16);
   1459     }
   1460   }
   1461 
   1462   /* Make sure PROTO_MODE is processed as last */
   1463   for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
   1464     if (charac.uuid == Uuid::From16Bit(GATT_UUID_HID_PROTO_MODE)) {
   1465       p_dev_cb->hid_srvc.proto_mode_handle = charac.value_handle;
   1466       bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
   1467       break;
   1468     }
   1469   }
   1470 }
   1471 
   1472 /*******************************************************************************
   1473  *
   1474  * Function         bta_hh_le_srvc_search_cmpl
   1475  *
   1476  * Description      This function process the GATT service search complete.
   1477  *
   1478  * Parameters:
   1479  *
   1480  ******************************************************************************/
   1481 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) {
   1482   tBTA_HH_DEV_CB* p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   1483 
   1484   /* service search exception or no HID service is supported on remote */
   1485   if (p_dev_cb == NULL) return;
   1486 
   1487   if (p_data->status != GATT_SUCCESS) {
   1488     p_dev_cb->status = BTA_HH_ERR_SDP;
   1489     /* close the connection and report service discovery complete with error */
   1490     bta_hh_le_api_disc_act(p_dev_cb);
   1491     return;
   1492   }
   1493 
   1494   const std::vector<tBTA_GATTC_SERVICE>* services =
   1495       BTA_GATTC_GetServices(p_data->conn_id);
   1496 
   1497   bool have_hid = false;
   1498   for (const tBTA_GATTC_SERVICE& service : *services) {
   1499     if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_LE_HID) &&
   1500         service.is_primary && !have_hid) {
   1501       have_hid = true;
   1502 
   1503       /* found HID primamry service */
   1504       p_dev_cb->hid_srvc.in_use = true;
   1505       p_dev_cb->hid_srvc.srvc_inst_id = service.handle;
   1506       p_dev_cb->hid_srvc.proto_mode_handle = 0;
   1507       p_dev_cb->hid_srvc.control_point_handle = 0;
   1508 
   1509       bta_hh_le_search_hid_chars(p_dev_cb, &service);
   1510 
   1511       APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__,
   1512                        p_dev_cb->hid_srvc.srvc_inst_id);
   1513     } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_SCAN_PARAM)) {
   1514       p_dev_cb->scan_refresh_char_handle = 0;
   1515 
   1516       for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
   1517         if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) {
   1518           p_dev_cb->scan_refresh_char_handle = charac.value_handle;
   1519 
   1520           if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY)
   1521             p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
   1522           else
   1523             p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
   1524 
   1525           break;
   1526         }
   1527       }
   1528     } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
   1529       // TODO(jpawlowski): this should be done by GAP profile, remove when GAP
   1530       // is fixed.
   1531       for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
   1532         if (charac.uuid == Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM)) {
   1533           /* read the char value */
   1534           BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id,
   1535                                            charac.value_handle,
   1536                                            read_pref_conn_params_cb, p_dev_cb);
   1537           break;
   1538         }
   1539       }
   1540     }
   1541   }
   1542 
   1543   bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
   1544 }
   1545 
   1546 /*******************************************************************************
   1547  *
   1548  * Function         bta_hh_le_input_rpt_notify
   1549  *
   1550  * Description      process the notificaton event, most likely for input report.
   1551  *
   1552  * Parameters:
   1553  *
   1554  ******************************************************************************/
   1555 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY* p_data) {
   1556   tBTA_HH_DEV_CB* p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   1557   uint8_t app_id;
   1558   uint8_t* p_buf;
   1559   tBTA_HH_LE_RPT* p_rpt;
   1560 
   1561   if (p_dev_cb == NULL) {
   1562     APPL_TRACE_ERROR(
   1563         "%s: notification received from Unknown device, conn_id: 0x%04x",
   1564         __func__, p_data->conn_id);
   1565     return;
   1566   }
   1567 
   1568   const tBTA_GATTC_CHARACTERISTIC* p_char =
   1569       BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id, p_data->handle);
   1570   if (p_char == NULL) {
   1571     APPL_TRACE_ERROR(
   1572         "%s: notification received for Unknown Characteristic, conn_id: "
   1573         "0x%04x, handle: 0x%04x",
   1574         __func__, p_dev_cb->conn_id, p_data->handle);
   1575     return;
   1576   }
   1577 
   1578   app_id = p_dev_cb->app_id;
   1579 
   1580   p_rpt =
   1581       bta_hh_le_find_report_entry(p_dev_cb, p_dev_cb->hid_srvc.srvc_inst_id,
   1582                                   p_char->uuid.As16Bit(), p_char->value_handle);
   1583   if (p_rpt == NULL) {
   1584     APPL_TRACE_ERROR(
   1585         "%s: notification received for Unknown Report, uuid: %s, handle: "
   1586         "0x%04x",
   1587         __func__, p_char->uuid.ToString().c_str(), p_char->value_handle);
   1588     return;
   1589   }
   1590 
   1591   if (p_char->uuid == Uuid::From16Bit(GATT_UUID_HID_BT_MOUSE_INPUT))
   1592     app_id = BTA_HH_APP_ID_MI;
   1593   else if (p_char->uuid == Uuid::From16Bit(GATT_UUID_HID_BT_KB_INPUT))
   1594     app_id = BTA_HH_APP_ID_KB;
   1595 
   1596   APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
   1597 
   1598   /* need to append report ID to the head of data */
   1599   if (p_rpt->rpt_id != 0) {
   1600     p_buf = (uint8_t*)osi_malloc(p_data->len + 1);
   1601 
   1602     p_buf[0] = p_rpt->rpt_id;
   1603     memcpy(&p_buf[1], p_data->value, p_data->len);
   1604     ++p_data->len;
   1605   } else {
   1606     p_buf = p_data->value;
   1607   }
   1608 
   1609   bta_hh_co_data((uint8_t)p_dev_cb->hid_handle, p_buf, p_data->len,
   1610                  p_dev_cb->mode, 0, /* no sub class*/
   1611                  p_dev_cb->dscp_info.ctry_code, p_dev_cb->addr, app_id);
   1612 
   1613   if (p_buf != p_data->value) osi_free(p_buf);
   1614 }
   1615 
   1616 /*******************************************************************************
   1617  *
   1618  * Function         bta_hh_gatt_open_fail
   1619  *
   1620  * Description      action function to process the open fail
   1621  *
   1622  * Returns          void
   1623  *
   1624  ******************************************************************************/
   1625 void bta_hh_le_open_fail(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
   1626   tBTA_HH_CONN conn_dat;
   1627 
   1628   /* open failure in the middle of service discovery, clear all services */
   1629   if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS) {
   1630     bta_hh_clear_service_cache(p_cb);
   1631   }
   1632 
   1633   p_cb->disc_active = BTA_HH_LE_DISC_NONE;
   1634   /* Failure in opening connection or GATT discovery failure */
   1635   conn_dat.handle = p_cb->hid_handle;
   1636   conn_dat.bda = p_cb->addr;
   1637   conn_dat.le_hid = true;
   1638   conn_dat.scps_supported = p_cb->scps_supported;
   1639 
   1640   if (p_cb->status == BTA_HH_OK)
   1641     conn_dat.status = (p_data->le_close.reason == GATT_CONN_UNKNOWN)
   1642                           ? p_cb->status
   1643                           : BTA_HH_ERR;
   1644   else
   1645     conn_dat.status = p_cb->status;
   1646 
   1647   /* Report OPEN fail event */
   1648   (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
   1649 }
   1650 
   1651 /*******************************************************************************
   1652  *
   1653  * Function         bta_hh_gatt_close
   1654  *
   1655  * Description      action function to process the GATT close int he state
   1656  *                  machine.
   1657  *
   1658  * Returns          void
   1659  *
   1660  ******************************************************************************/
   1661 void bta_hh_gatt_close(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
   1662   tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
   1663 
   1664   /* deregister all notification */
   1665   bta_hh_le_deregister_input_notif(p_cb);
   1666   /* finaliza device driver */
   1667   bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
   1668   /* update total conn number */
   1669   bta_hh_cb.cnt_num--;
   1670 
   1671   disc_dat.handle = p_cb->hid_handle;
   1672   disc_dat.status = p_cb->status;
   1673 
   1674   (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH*)&disc_dat);
   1675 
   1676   /* if no connection is active and HH disable is signaled, disable service */
   1677   if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
   1678     bta_hh_disc_cmpl();
   1679   } else {
   1680 #if (BTA_HH_LE_RECONN == TRUE)
   1681     if (p_data->le_close.reason == GATT_CONN_TIMEOUT) {
   1682       bta_hh_le_add_dev_bg_conn(p_cb, false);
   1683     }
   1684 #endif
   1685   }
   1686 
   1687   return;
   1688 }
   1689 
   1690 /*******************************************************************************
   1691  *
   1692  * Function         bta_hh_le_api_disc_act
   1693  *
   1694  * Description      initaite a Close API to a remote HID device
   1695  *
   1696  * Returns          void
   1697  *
   1698  ******************************************************************************/
   1699 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb) {
   1700   if (p_cb->conn_id != GATT_INVALID_CONN_ID) {
   1701     BtaGattQueue::Clean(p_cb->conn_id);
   1702     BTA_GATTC_Close(p_cb->conn_id);
   1703     /* remove device from background connection if intended to disconnect,
   1704        do not allow reconnection */
   1705     bta_hh_le_remove_dev_bg_conn(p_cb);
   1706   }
   1707 }
   1708 
   1709 /*******************************************************************************
   1710  *
   1711  * Function         read_report_cb
   1712  *
   1713  * Description      Process the Read report complete, send GET_REPORT_EVT to
   1714  *                  application with the report data.
   1715  *
   1716  * Parameters:
   1717  *
   1718  ******************************************************************************/
   1719 static void read_report_cb(uint16_t conn_id, tGATT_STATUS status,
   1720                            uint16_t handle, uint16_t len, uint8_t* value,
   1721                            void* data) {
   1722   const tBTA_GATTC_CHARACTERISTIC* p_char =
   1723       BTA_GATTC_GetCharacteristic(conn_id, handle);
   1724 
   1725   if (p_char == NULL) return;
   1726 
   1727   uint16_t char_uuid = p_char->uuid.As16Bit();
   1728 
   1729   if (char_uuid != GATT_UUID_HID_REPORT &&
   1730       char_uuid != GATT_UUID_HID_BT_KB_INPUT &&
   1731       char_uuid != GATT_UUID_HID_BT_KB_OUTPUT &&
   1732       char_uuid != GATT_UUID_HID_BT_MOUSE_INPUT &&
   1733       char_uuid != GATT_UUID_BATTERY_LEVEL) {
   1734     APPL_TRACE_ERROR("%s: Unexpected Read UUID: 0x%04x", __func__, char_uuid);
   1735     return;
   1736   }
   1737 
   1738   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1739   if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) {
   1740     APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
   1741     return;
   1742   }
   1743 
   1744   /* GET_REPORT */
   1745   BT_HDR* p_buf = NULL;
   1746   tBTA_HH_LE_RPT* p_rpt;
   1747   tBTA_HH_HSDATA hs_data;
   1748   uint8_t* pp;
   1749 
   1750   memset(&hs_data, 0, sizeof(hs_data));
   1751   hs_data.status = BTA_HH_ERR;
   1752   hs_data.handle = p_dev_cb->hid_handle;
   1753 
   1754   if (status == GATT_SUCCESS) {
   1755     const tBTA_GATTC_SERVICE* p_svc =
   1756         BTA_GATTC_GetOwningService(conn_id, p_char->value_handle);
   1757 
   1758     p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid,
   1759                                         p_char->value_handle);
   1760 
   1761     if (p_rpt != NULL && len) {
   1762       p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1);
   1763       /* pack data send to app */
   1764       hs_data.status = BTA_HH_OK;
   1765       p_buf->len = len + 1;
   1766       p_buf->layer_specific = 0;
   1767       p_buf->offset = 0;
   1768 
   1769       /* attach report ID as the first byte of the report before sending it to
   1770        * USB HID driver */
   1771       pp = (uint8_t*)(p_buf + 1);
   1772       UINT8_TO_STREAM(pp, p_rpt->rpt_id);
   1773       memcpy(pp, value, len);
   1774 
   1775       hs_data.rsp_data.p_rpt_data = p_buf;
   1776     }
   1777   }
   1778 
   1779   p_dev_cb->w4_evt = 0;
   1780   (*bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH*)&hs_data);
   1781 
   1782   osi_free_and_reset((void**)&p_buf);
   1783 }
   1784 
   1785 /*******************************************************************************
   1786  *
   1787  * Function         bta_hh_le_get_rpt
   1788  *
   1789  * Description      GET_REPORT on a LE HID Report
   1790  *
   1791  * Returns          void
   1792  *
   1793  ******************************************************************************/
   1794 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type,
   1795                        uint8_t rpt_id) {
   1796   tBTA_HH_LE_RPT* p_rpt = bta_hh_le_find_rpt_by_idtype(
   1797       p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
   1798 
   1799   if (p_rpt == NULL) {
   1800     APPL_TRACE_ERROR("%s: no matching report", __func__);
   1801     return;
   1802   }
   1803 
   1804   p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
   1805   BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_rpt->char_inst_id,
   1806                                    read_report_cb, p_cb);
   1807 }
   1808 
   1809 static void write_report_cb(uint16_t conn_id, tGATT_STATUS status,
   1810                             uint16_t handle, void* data) {
   1811   tBTA_HH_CBDATA cback_data;
   1812   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
   1813   uint16_t cb_evt = p_dev_cb->w4_evt;
   1814 
   1815   if (cb_evt == 0) return;
   1816 
   1817 #if (BTA_HH_DEBUG == TRUE)
   1818   APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
   1819 #endif
   1820 
   1821   const tBTA_GATTC_CHARACTERISTIC* p_char =
   1822       BTA_GATTC_GetCharacteristic(conn_id, handle);
   1823   uint16_t uuid = p_char->uuid.As16Bit();
   1824   if (uuid != GATT_UUID_HID_REPORT && uuid != GATT_UUID_HID_BT_KB_INPUT &&
   1825       uuid != GATT_UUID_HID_BT_MOUSE_INPUT &&
   1826       uuid != GATT_UUID_HID_BT_KB_OUTPUT) {
   1827     return;
   1828   }
   1829 
   1830   /* Set Report finished */
   1831   cback_data.handle = p_dev_cb->hid_handle;
   1832   cback_data.status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR;
   1833   p_dev_cb->w4_evt = 0;
   1834   (*bta_hh_cb.p_cback)(cb_evt, (tBTA_HH*)&cback_data);
   1835 }
   1836 /*******************************************************************************
   1837  *
   1838  * Function         bta_hh_le_write_rpt
   1839  *
   1840  * Description      SET_REPORT/or DATA output on a LE HID Report
   1841  *
   1842  * Returns          void
   1843  *
   1844  ******************************************************************************/
   1845 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type,
   1846                          BT_HDR* p_buf, uint16_t w4_evt) {
   1847   tBTA_HH_LE_RPT* p_rpt;
   1848   uint8_t rpt_id;
   1849 
   1850   if (p_buf == NULL || p_buf->len == 0) {
   1851     APPL_TRACE_ERROR("%s: Illegal data", __func__);
   1852     return;
   1853   }
   1854 
   1855   /* strip report ID from the data */
   1856   uint8_t* vec_start = (uint8_t*)(p_buf + 1) + p_buf->offset;
   1857   STREAM_TO_UINT8(rpt_id, vec_start);
   1858   vector<uint8_t> value(vec_start, vec_start + p_buf->len - 1);
   1859 
   1860   p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode,
   1861                                        r_type, rpt_id);
   1862   if (p_rpt == NULL) {
   1863     APPL_TRACE_ERROR("%s: no matching report", __func__);
   1864     osi_free(p_buf);
   1865     return;
   1866   }
   1867 
   1868   p_cb->w4_evt = w4_evt;
   1869 
   1870   const tBTA_GATTC_CHARACTERISTIC* p_char =
   1871       BTA_GATTC_GetCharacteristic(p_cb->conn_id, p_rpt->char_inst_id);
   1872 
   1873   tGATT_WRITE_TYPE write_type = GATT_WRITE;
   1874   if (p_char && (p_char->properties & GATT_CHAR_PROP_BIT_WRITE_NR))
   1875     write_type = GATT_WRITE_NO_RSP;
   1876 
   1877   BtaGattQueue::WriteCharacteristic(p_cb->conn_id, p_rpt->char_inst_id,
   1878                                     std::move(value), write_type,
   1879                                     write_report_cb, p_cb);
   1880 }
   1881 
   1882 /*******************************************************************************
   1883  *
   1884  * Function         bta_hh_le_suspend
   1885  *
   1886  * Description      send LE suspend or exit suspend mode to remote device.
   1887  *
   1888  * Returns          void
   1889  *
   1890  ******************************************************************************/
   1891 void bta_hh_le_suspend(tBTA_HH_DEV_CB* p_cb,
   1892                        tBTA_HH_TRANS_CTRL_TYPE ctrl_type) {
   1893   ctrl_type -= BTA_HH_CTRL_SUSPEND;
   1894 
   1895   // We don't care about response
   1896   BtaGattQueue::WriteCharacteristic(
   1897       p_cb->conn_id, p_cb->hid_srvc.control_point_handle, {(uint8_t)ctrl_type},
   1898       GATT_WRITE_NO_RSP, NULL, NULL);
   1899 }
   1900 
   1901 /*******************************************************************************
   1902  *
   1903  * Function         bta_hh_le_write_dev_act
   1904  *
   1905  * Description      Write LE device action. can be SET/GET/DATA transaction.
   1906  *
   1907  * Returns          void
   1908  *
   1909  ******************************************************************************/
   1910 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
   1911   switch (p_data->api_sndcmd.t_type) {
   1912     case HID_TRANS_SET_PROTOCOL:
   1913       p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
   1914       bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
   1915       break;
   1916 
   1917     case HID_TRANS_GET_PROTOCOL:
   1918       bta_hh_le_get_protocol_mode(p_cb);
   1919       break;
   1920 
   1921     case HID_TRANS_GET_REPORT:
   1922       bta_hh_le_get_rpt(p_cb, p_data->api_sndcmd.param,
   1923                         p_data->api_sndcmd.rpt_id);
   1924       break;
   1925 
   1926     case HID_TRANS_SET_REPORT:
   1927       bta_hh_le_write_rpt(p_cb, p_data->api_sndcmd.param,
   1928                           p_data->api_sndcmd.p_data, BTA_HH_SET_RPT_EVT);
   1929       break;
   1930 
   1931     case HID_TRANS_DATA: /* output report */
   1932 
   1933       bta_hh_le_write_rpt(p_cb, p_data->api_sndcmd.param,
   1934                           p_data->api_sndcmd.p_data, BTA_HH_DATA_EVT);
   1935       break;
   1936 
   1937     case HID_TRANS_CONTROL:
   1938       /* no handshake event will be generated */
   1939       /* if VC_UNPLUG is issued, set flag */
   1940       if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
   1941           p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND) {
   1942         bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
   1943       }
   1944       break;
   1945 
   1946     default:
   1947       APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
   1948                        __func__, p_data->api_sndcmd.t_type);
   1949       break;
   1950   }
   1951 }
   1952 
   1953 /*******************************************************************************
   1954  *
   1955  * Function         bta_hh_le_get_dscp_act
   1956  *
   1957  * Description      Send ReportDescriptor to application for all HID services.
   1958  *
   1959  * Returns          void
   1960  *
   1961  ******************************************************************************/
   1962 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB* p_cb) {
   1963   if (p_cb->hid_srvc.in_use) {
   1964     p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len;
   1965     p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list;
   1966 
   1967     (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH*)&p_cb->dscp_info);
   1968   }
   1969 }
   1970 
   1971 /*******************************************************************************
   1972  *
   1973  * Function         bta_hh_le_add_dev_bg_conn
   1974  *
   1975  * Description      Remove a LE HID device from back ground connection
   1976  *                  procedure.
   1977  *
   1978  * Returns          void
   1979  *
   1980  ******************************************************************************/
   1981 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB* p_cb, bool check_bond) {
   1982   uint8_t sec_flag = 0;
   1983   bool to_add = true;
   1984 
   1985   if (check_bond) {
   1986     /* start reconnection if remote is a bonded device */
   1987     /* verify bond */
   1988     BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   1989 
   1990     if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0) to_add = false;
   1991   }
   1992 
   1993   if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
   1994       !p_cb->in_bg_conn && to_add) {
   1995     /* add device into BG connection to accept remote initiated connection */
   1996     BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, false, GATT_TRANSPORT_LE,
   1997                    false);
   1998     p_cb->in_bg_conn = true;
   1999 
   2000     BTA_DmBleStartAutoConn();
   2001   }
   2002   return;
   2003 }
   2004 
   2005 /*******************************************************************************
   2006  *
   2007  * Function         bta_hh_le_add_device
   2008  *
   2009  * Description      Add a LE HID device as a known device, and also add the
   2010  *                  address
   2011  *                  into back ground connection WL for incoming connection.
   2012  *
   2013  * Returns          void
   2014  *
   2015  ******************************************************************************/
   2016 uint8_t bta_hh_le_add_device(tBTA_HH_DEV_CB* p_cb,
   2017                              tBTA_HH_MAINT_DEV* p_dev_info) {
   2018   p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
   2019   if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) return BTA_HH_INVALID_HANDLE;
   2020   bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   2021 
   2022   /* update DI information */
   2023   bta_hh_update_di_info(
   2024       p_cb, p_dev_info->dscp_info.vendor_id, p_dev_info->dscp_info.product_id,
   2025       p_dev_info->dscp_info.version, p_dev_info->dscp_info.flag);
   2026 
   2027   /* add to BTA device list */
   2028   bta_hh_add_device_to_list(
   2029       p_cb, p_cb->hid_handle, p_dev_info->attr_mask,
   2030       &p_dev_info->dscp_info.descriptor, p_dev_info->sub_class,
   2031       p_dev_info->dscp_info.ssr_max_latency, p_dev_info->dscp_info.ssr_min_tout,
   2032       p_dev_info->app_id);
   2033 
   2034   bta_hh_le_add_dev_bg_conn(p_cb, false);
   2035 
   2036   return p_cb->hid_handle;
   2037 }
   2038 
   2039 /*******************************************************************************
   2040  *
   2041  * Function         bta_hh_le_remove_dev_bg_conn
   2042  *
   2043  * Description      Remove a LE HID device from back ground connection
   2044  *                  procedure.
   2045  *
   2046  * Returns          void
   2047  *
   2048  ******************************************************************************/
   2049 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB* p_dev_cb) {
   2050   if (p_dev_cb->in_bg_conn) {
   2051     p_dev_cb->in_bg_conn = false;
   2052 
   2053     BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, false);
   2054   }
   2055 
   2056   /* deregister all notifications */
   2057   bta_hh_le_deregister_input_notif(p_dev_cb);
   2058 }
   2059 
   2060 /*******************************************************************************
   2061  *
   2062  * Function         bta_hh_gattc_callback
   2063  *
   2064  * Description      This is GATT client callback function used in BTA HH.
   2065  *
   2066  * Parameters:
   2067  *
   2068  ******************************************************************************/
   2069 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
   2070   tBTA_HH_DEV_CB* p_dev_cb;
   2071 #if (BTA_HH_DEBUG == TRUE)
   2072   APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
   2073 #endif
   2074   if (p_data == NULL) return;
   2075 
   2076   switch (event) {
   2077     case BTA_GATTC_DEREG_EVT: /* 1 */
   2078       bta_hh_cleanup_disable(p_data->reg_oper.status);
   2079       break;
   2080 
   2081     case BTA_GATTC_OPEN_EVT: /* 2 */
   2082       p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
   2083       if (p_dev_cb) {
   2084         bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT,
   2085                           (tBTA_HH_DATA*)&p_data->open);
   2086       }
   2087       break;
   2088 
   2089     case BTA_GATTC_CLOSE_EVT: /* 5 */
   2090       bta_hh_le_close(&p_data->close);
   2091       break;
   2092 
   2093     case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
   2094       bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
   2095       break;
   2096 
   2097     case BTA_GATTC_NOTIF_EVT: /* 10 */
   2098       bta_hh_le_input_rpt_notify(&p_data->notify);
   2099       break;
   2100 
   2101     case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
   2102       p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
   2103       if (p_dev_cb) {
   2104         bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
   2105                           (tBTA_HH_DATA*)&p_data->enc_cmpl);
   2106       }
   2107       break;
   2108 
   2109     default:
   2110       break;
   2111   }
   2112 }
   2113 
   2114 static void read_report_descriptor_ccc_cb(uint16_t conn_id, tGATT_STATUS status,
   2115                                           uint16_t handle, uint16_t len,
   2116                                           uint8_t* value, void* data) {
   2117   tBTA_HH_LE_RPT* p_rpt = (tBTA_HH_LE_RPT*)data;
   2118   uint8_t* pp = value;
   2119   STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
   2120 
   2121   APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x",
   2122                    p_rpt->client_cfg_value);
   2123 }
   2124 
   2125 /*******************************************************************************
   2126  *
   2127  * Function         bta_hh_le_hid_read_rpt_clt_cfg
   2128  *
   2129  * Description      a test command to read report descriptor client
   2130  *                  configuration
   2131  *
   2132  * Returns          void
   2133  *
   2134  ******************************************************************************/
   2135 void bta_hh_le_hid_read_rpt_clt_cfg(const RawAddress& bd_addr, uint8_t rpt_id) {
   2136   tBTA_HH_DEV_CB* p_cb = NULL;
   2137   tBTA_HH_LE_RPT* p_rpt;
   2138   uint8_t index = BTA_HH_IDX_INVALID;
   2139 
   2140   index = bta_hh_find_cb(bd_addr);
   2141   if (index == BTA_HH_IDX_INVALID) {
   2142     APPL_TRACE_ERROR("%s: unknown device", __func__);
   2143     return;
   2144   }
   2145 
   2146   p_cb = &bta_hh_cb.kdev[index];
   2147 
   2148   p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode,
   2149                                        BTA_HH_RPTT_INPUT, rpt_id);
   2150 
   2151   if (p_rpt == NULL) {
   2152     APPL_TRACE_ERROR("%s: no matching report", __func__);
   2153     return;
   2154   }
   2155 
   2156   bta_hh_le_read_char_descriptor(p_cb, p_rpt->char_inst_id,
   2157                                  GATT_UUID_CHAR_CLIENT_CONFIG,
   2158                                  read_report_descriptor_ccc_cb, p_rpt);
   2159   return;
   2160 }
   2161 
   2162 /*******************************************************************************
   2163  *
   2164  * Function         bta_hh_process_cache_rpt
   2165  *
   2166  * Description      Process the cached reports
   2167  *
   2168  * Parameters:
   2169  *
   2170  ******************************************************************************/
   2171 // TODO(jpawlowski): uncomment when fixed
   2172 // static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
   2173 //                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
   2174 //                                       uint8_t num_rpt)
   2175 // {
   2176 //     uint8_t                       i = 0;
   2177 //     tBTA_HH_LE_RPT              *p_rpt;
   2178 
   2179 //     if (num_rpt != 0)  /* no cache is found */
   2180 //     {
   2181 //         p_cb->hid_srvc.in_use = true;
   2182 
   2183 //         /* set the descriptor info */
   2184 //         p_cb->hid_srvc.descriptor.dl_len =
   2185 //                 p_cb->dscp_info.descriptor.dl_len;
   2186 //         p_cb->hid_srvc.descriptor.dsc_list =
   2187 //                     p_cb->dscp_info.descriptor.dsc_list;
   2188 
   2189 //         for (; i <num_rpt; i ++, p_rpt_cache ++)
   2190 //         {
   2191 //             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
   2192 //                                                p_rpt_cache->srvc_inst_id,
   2193 //                                                p_rpt_cache->rpt_uuid,
   2194 //                                                p_rpt_cache->char_inst_id,
   2195 //                                                p_rpt_cache->prop))  == NULL)
   2196 //             {
   2197 //                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report
   2198 //                 entry failure");
   2199 //                 break;
   2200 //             }
   2201 //             else
   2202 //             {
   2203 //                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
   2204 //                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
   2205 
   2206 //                 if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
   2207 //                     p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
   2208 //                     (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type
   2209 //                     == BTA_HH_RPTT_INPUT))
   2210 //                 {
   2211 //                     p_rpt->client_cfg_value =
   2212 //                     GATT_CLT_CONFIG_NOTIFICATION;
   2213 //                 }
   2214 //             }
   2215 //         }
   2216 //     }
   2217 // }
   2218 
   2219 #endif
   2220