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