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