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("---> Deregister Report ID: %d", 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("<--- Register Boot Report ID: %d", 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("---> Deregister Boot Report ID: %d", 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("<--- Register Report ID: %d", 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_open_cmpl
    846 **
    847 ** Description      HID over GATT connection sucessfully opened
    848 **
    849 *******************************************************************************/
    850 void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
    851 {
    852     if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
    853     {
    854 #if BTA_HH_DEBUG
    855         bta_hh_le_hid_report_dbg(p_cb);
    856 #endif
    857         bta_hh_le_register_input_notif(p_cb, p_cb->mode, TRUE);
    858         bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
    859 
    860 #if (BTA_HH_LE_RECONN == TRUE)
    861         if (p_cb->status == BTA_HH_OK)
    862         {
    863             bta_hh_le_add_dev_bg_conn(p_cb, TRUE);
    864         }
    865 #endif
    866     }
    867 }
    868 
    869 /*******************************************************************************
    870 **
    871 ** Function         bta_hh_le_write_char_clt_cfg
    872 **
    873 ** Description      Utility function to find and write client configuration of
    874 **                  a characteristic
    875 **
    876 *******************************************************************************/
    877 BOOLEAN bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB *p_cb,
    878                                      UINT8 char_handle,
    879                                      UINT16 clt_cfg_value)
    880 {
    881     UINT8                      buf[2], *pp = buf;
    882 
    883     tBTA_GATTC_DESCRIPTOR *p_desc = find_descriptor_by_short_uuid(p_cb->conn_id,
    884                                        char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
    885     if (!p_desc)
    886         return FALSE;
    887 
    888     UINT16_TO_STREAM(pp, clt_cfg_value);
    889     gatt_queue_write_op(GATT_WRITE_DESC, p_cb->conn_id,
    890                         p_desc->handle, 2, buf, BTA_GATTC_TYPE_WRITE);
    891     return TRUE;
    892 }
    893 
    894 /*******************************************************************************
    895 **
    896 ** Function         bta_hh_le_write_rpt_clt_cfg
    897 **
    898 ** Description      write client configuration. This is only for input report
    899 **                  enable all input notification upon connection open.
    900 **
    901 *******************************************************************************/
    902 BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
    903 {
    904     UINT8           i;
    905     tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[p_cb->clt_cfg_idx];
    906 
    907     for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
    908     {
    909         /* enable notification for all input report, regardless mode */
    910         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
    911         {
    912             if (bta_hh_le_write_char_clt_cfg(p_cb,
    913                                              p_rpt->char_inst_id,
    914                                              BTA_GATT_CLT_CONFIG_NOTIFICATION))
    915             {
    916                 p_cb->clt_cfg_idx = i;
    917                 return TRUE;
    918             }
    919         }
    920     }
    921     p_cb->clt_cfg_idx = 0;
    922 
    923     /* client configuration is completed, send open callback */
    924     if (p_cb->state == BTA_HH_W4_CONN_ST)
    925     {
    926         p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
    927 
    928         bta_hh_le_open_cmpl(p_cb);
    929     }
    930     return FALSE;
    931 }
    932 
    933 /*******************************************************************************
    934 **
    935 ** Function         bta_hh_le_set_protocol_mode
    936 **
    937 ** Description      Set remote device protocol mode.
    938 **
    939 *******************************************************************************/
    940 BOOLEAN bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
    941 {
    942     tBTA_HH_CBDATA      cback_data;
    943     BOOLEAN             exec = FALSE;
    944 
    945     APPL_TRACE_DEBUG("%s attempt mode: %s", __func__,
    946                      (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
    947 
    948     cback_data.handle  = p_cb->hid_handle;
    949     /* boot mode is not supported in the remote device */
    950     if (p_cb->hid_srvc.proto_mode_handle == 0)
    951     {
    952         p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
    953 
    954         if (mode == BTA_HH_PROTO_BOOT_MODE)
    955         {
    956             APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
    957             cback_data.status = BTA_HH_ERR;
    958         }
    959         else
    960         {
    961             /* if set to report mode, need to de-register all input report notification */
    962             bta_hh_le_register_input_notif(p_cb, p_cb->mode, FALSE);
    963             cback_data.status = BTA_HH_OK;
    964         }
    965         if (p_cb->state == BTA_HH_W4_CONN_ST)
    966         {
    967             p_cb->status = (cback_data.status == BTA_HH_OK)? BTA_HH_OK: BTA_HH_ERR_PROTO;
    968         }
    969         else
    970             (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
    971     } else if (p_cb->mode != mode) {
    972         p_cb->mode = mode;
    973         mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
    974 
    975         gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, 1,
    976                             &mode, BTA_GATTC_TYPE_WRITE_NO_RSP);
    977         exec        = TRUE;
    978     }
    979 
    980     return exec;
    981 }
    982 
    983 /*******************************************************************************
    984 **
    985 ** Function         bta_hh_le_get_protocol_mode
    986 **
    987 ** Description      Get remote device protocol mode.
    988 **
    989 *******************************************************************************/
    990 void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
    991 {
    992     tBTA_HH_HSDATA    hs_data;
    993     p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
    994 
    995     if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
    996         gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle);
    997         return;
    998     }
    999 
   1000     /* no service support protocol_mode, by default report mode */
   1001     hs_data.status  = BTA_HH_OK;
   1002     hs_data.handle  = p_cb->hid_handle;
   1003     hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
   1004     p_cb->w4_evt = 0;
   1005     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
   1006 }
   1007 
   1008 /*******************************************************************************
   1009 **
   1010 ** Function         bta_hh_le_dis_cback
   1011 **
   1012 ** Description      DIS read complete callback
   1013 **
   1014 ** Parameters:
   1015 **
   1016 *******************************************************************************/
   1017 void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
   1018 {
   1019     tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
   1020 
   1021 
   1022     if (p_cb == NULL || p_dis_value == NULL)
   1023     {
   1024         APPL_TRACE_ERROR("received unexpected/error DIS callback");
   1025         return;
   1026     }
   1027 
   1028     p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
   1029     /* plug in the PnP info for this device */
   1030     if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT)
   1031     {
   1032 #if BTA_HH_DEBUG == TRUE
   1033         APPL_TRACE_DEBUG("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
   1034                 p_dis_value->pnp_id.product_id,
   1035                 p_dis_value->pnp_id.vendor_id,
   1036                 p_dis_value->pnp_id.product_version);
   1037 #endif
   1038         p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
   1039         p_cb->dscp_info.vendor_id  = p_dis_value->pnp_id.vendor_id;
   1040         p_cb->dscp_info.version    = p_dis_value->pnp_id.product_version;
   1041     }
   1042     bta_hh_le_open_cmpl(p_cb);
   1043 }
   1044 
   1045 /*******************************************************************************
   1046 **
   1047 ** Function         bta_hh_le_pri_service_discovery
   1048 **
   1049 ** Description      Initialize GATT discovery on the remote LE HID device by opening
   1050 **                  a GATT connection first.
   1051 **
   1052 ** Parameters:
   1053 **
   1054 *******************************************************************************/
   1055 void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
   1056 {
   1057     tBT_UUID        pri_srvc;
   1058 
   1059     bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
   1060 
   1061     p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
   1062 
   1063     /* read DIS info */
   1064     if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT))
   1065     {
   1066         APPL_TRACE_ERROR("read DIS failed");
   1067         p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
   1068     }
   1069 
   1070     /* in parallel */
   1071     /* start primary service discovery for HID service */
   1072     pri_srvc.len        = LEN_UUID_16;
   1073     pri_srvc.uu.uuid16  = UUID_SERVCLASS_LE_HID;
   1074     BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
   1075     return;
   1076 }
   1077 
   1078 /*******************************************************************************
   1079 **
   1080 ** Function         bta_hh_le_encrypt_cback
   1081 **
   1082 ** Description      link encryption complete callback for bond verification.
   1083 **
   1084 ** Returns          None
   1085 **
   1086 *******************************************************************************/
   1087 void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
   1088                                     void *p_ref_data, tBTM_STATUS result)
   1089 {
   1090     UINT8   idx = bta_hh_find_cb(bd_addr);
   1091     tBTA_HH_DEV_CB *p_dev_cb;
   1092     UNUSED(p_ref_data);
   1093     UNUSED (transport);
   1094 
   1095     if (idx != BTA_HH_IDX_INVALID)
   1096         p_dev_cb = &bta_hh_cb.kdev[idx];
   1097     else
   1098     {
   1099         APPL_TRACE_ERROR("unexpected encryption callback, ignore");
   1100         return;
   1101     }
   1102     p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
   1103     p_dev_cb->reason = result;
   1104 
   1105     bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1106 }
   1107 
   1108 /*******************************************************************************
   1109 **
   1110 ** Function         bta_hh_security_cmpl
   1111 **
   1112 ** Description      Security check completed, start the service discovery
   1113 **                  if no cache available, otherwise report connection open completed
   1114 **
   1115 ** Parameters:
   1116 **
   1117 *******************************************************************************/
   1118 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1119 {
   1120     UNUSED(p_buf);
   1121 
   1122     APPL_TRACE_DEBUG("%s", __func__);
   1123     if (p_cb->status == BTA_HH_OK)
   1124     {
   1125         if (!p_cb->hid_srvc.in_use)
   1126         {
   1127             APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
   1128 
   1129             /* start loading the cache if not in stack */
   1130             //TODO(jpawlowski): cache storage is broken, fix it
   1131             // tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
   1132             // UINT8                       num_rpt = 0;
   1133             // if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
   1134             // {
   1135             //     bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
   1136             // }
   1137         }
   1138         /*  discovery has been done for HID service */
   1139         if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use)
   1140         {
   1141             APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
   1142             /* configure protocol mode */
   1143             if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE)
   1144             {
   1145                 bta_hh_le_open_cmpl(p_cb);
   1146             }
   1147         }
   1148         /* start primary service discovery for HID service */
   1149         else
   1150         {
   1151             APPL_TRACE_DEBUG("%s: Starting service discovery", __func__);
   1152             bta_hh_le_pri_service_discovery(p_cb);
   1153         }
   1154     }
   1155     else
   1156     {
   1157         APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
   1158                 __FUNCTION__, p_cb->status, p_cb->reason);
   1159         if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
   1160             bta_hh_le_api_disc_act(p_cb);
   1161     }
   1162 }
   1163 
   1164 /*******************************************************************************
   1165 **
   1166 ** Function         bta_hh_le_notify_enc_cmpl
   1167 **
   1168 ** Description      process GATT encryption complete event
   1169 **
   1170 ** Returns
   1171 **
   1172 *******************************************************************************/
   1173 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1174 {
   1175     if (p_cb == NULL || p_cb->security_pending == FALSE ||
   1176         p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
   1177     {
   1178         return;
   1179     }
   1180 
   1181     p_cb->security_pending = FALSE;
   1182     bta_hh_start_security(p_cb, NULL);
   1183 }
   1184 
   1185 /*******************************************************************************
   1186 **
   1187 ** Function         bta_hh_clear_service_cache
   1188 **
   1189 ** Description      clear the service cache
   1190 **
   1191 ** Parameters:
   1192 **
   1193 *******************************************************************************/
   1194 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
   1195 {
   1196     tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc;
   1197 
   1198     p_cb->app_id = 0;
   1199     p_cb->dscp_info.descriptor.dsc_list = NULL;
   1200 
   1201     osi_free_and_reset((void **)&p_hid_srvc->rpt_map);
   1202     memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
   1203 }
   1204 
   1205 /*******************************************************************************
   1206 **
   1207 ** Function         bta_hh_start_security
   1208 **
   1209 ** Description      start the security check of the established connection
   1210 **
   1211 ** Parameters:
   1212 **
   1213 *******************************************************************************/
   1214 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1215 {
   1216     UINT8           sec_flag=0;
   1217     tBTM_SEC_DEV_REC  *p_dev_rec;
   1218     UNUSED(p_buf);
   1219 
   1220     p_dev_rec = btm_find_dev(p_cb->addr);
   1221     if (p_dev_rec)
   1222     {
   1223         if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
   1224             p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
   1225         {
   1226             /* if security collision happened, wait for encryption done */
   1227             p_cb->security_pending = TRUE;
   1228             return;
   1229         }
   1230     }
   1231 
   1232     /* verify bond */
   1233     BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   1234 
   1235     /* if link has been encrypted */
   1236     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
   1237     {
   1238         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1239     }
   1240     /* if bonded and link not encrypted */
   1241     else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
   1242     {
   1243         sec_flag = BTM_BLE_SEC_ENCRYPT;
   1244         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1245         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
   1246     }
   1247     /* unbonded device, report security error here */
   1248     else if (p_cb->sec_mask != BTA_SEC_NONE)
   1249     {
   1250         sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
   1251         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1252         bta_hh_clear_service_cache(p_cb);
   1253         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
   1254     }
   1255     /* otherwise let it go through */
   1256     else
   1257     {
   1258         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1259     }
   1260 
   1261 
   1262 }
   1263 
   1264 /*******************************************************************************
   1265 **
   1266 ** Function         bta_hh_gatt_open
   1267 **
   1268 ** Description      process GATT open event.
   1269 **
   1270 ** Parameters:
   1271 **
   1272 *******************************************************************************/
   1273 void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1274 {
   1275     tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
   1276     UINT8           *p2;
   1277     tHID_STATUS     status = BTA_HH_ERR;
   1278 
   1279     /* if received invalid callback data , ignore it */
   1280     if (p_cb == NULL || p_data == NULL)
   1281         return;
   1282 
   1283     p2 = p_data->remote_bda;
   1284 
   1285     APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
   1286                       ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
   1287                       ((p2[4])<<8)+ p2[5],p_data->status);
   1288 
   1289     if (p_data->status == BTA_GATT_OK)
   1290     {
   1291         p_cb->is_le_device  = TRUE;
   1292         p_cb->in_use    = TRUE;
   1293         p_cb->conn_id   = p_data->conn_id;
   1294         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
   1295 
   1296         bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   1297 
   1298         gatt_op_queue_clean(p_cb->conn_id);
   1299 
   1300 #if BTA_HH_DEBUG == TRUE
   1301         APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
   1302 #endif
   1303 
   1304         bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
   1305 
   1306     }
   1307     else /* open failure */
   1308     {
   1309         bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
   1310     }
   1311 
   1312 }
   1313 
   1314 /*******************************************************************************
   1315 **
   1316 ** Function         bta_hh_le_close
   1317 **
   1318 ** Description      This function process the GATT close event and post it as a
   1319 **                  BTA HH internal event
   1320 **
   1321 ** Parameters:
   1322 **
   1323 *******************************************************************************/
   1324 void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
   1325 {
   1326     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
   1327     UINT16  sm_event = BTA_HH_GATT_CLOSE_EVT;
   1328 
   1329     if (p_dev_cb != NULL) {
   1330         tBTA_HH_LE_CLOSE *p_buf =
   1331             (tBTA_HH_LE_CLOSE *)osi_malloc(sizeof(tBTA_HH_LE_CLOSE));
   1332         p_buf->hdr.event = sm_event;
   1333         p_buf->hdr.layer_specific = (UINT16)p_dev_cb->hid_handle;
   1334         p_buf->conn_id = p_data->conn_id;
   1335         p_buf->reason = p_data->reason;
   1336 
   1337         p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
   1338         p_dev_cb->security_pending = FALSE;
   1339         bta_sys_sendmsg(p_buf);
   1340     }
   1341 }
   1342 
   1343 /*******************************************************************************
   1344 **
   1345 ** Function         bta_hh_le_gatt_disc_cmpl
   1346 **
   1347 ** Description      Check to see if the remote device is a LE only device
   1348 **
   1349 ** Parameters:
   1350 **
   1351 *******************************************************************************/
   1352 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
   1353 {
   1354     APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
   1355 
   1356     /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
   1357     if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
   1358     {
   1359         /* assign a special APP ID temp, since device type unknown */
   1360         p_cb->app_id = BTA_HH_APP_ID_LE;
   1361 
   1362         /* set report notification configuration */
   1363         p_cb->clt_cfg_idx = 0;
   1364         bta_hh_le_write_rpt_clt_cfg(p_cb, p_cb->hid_srvc.srvc_inst_id);
   1365     }
   1366     else /* error, close the GATT connection */
   1367     {
   1368         /* close GATT connection if it's on */
   1369         bta_hh_le_api_disc_act(p_cb);
   1370     }
   1371 }
   1372 
   1373 void process_included(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service) {
   1374     if (!service->included_svc || list_is_empty(service->included_svc)) {
   1375         APPL_TRACE_ERROR("%s: Remote device does not have battery level", __func__);
   1376         return;
   1377     }
   1378 
   1379     for (list_node_t *isn = list_begin(service->included_svc);
   1380          isn != list_end(service->included_svc); isn = list_next(isn)) {
   1381         tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
   1382         tBTA_GATTC_SERVICE *incl_svc = p_isvc->included_service;
   1383         if (incl_svc->uuid.uu.uuid16 == UUID_SERVCLASS_BATTERY &&
   1384             incl_svc->uuid.len == LEN_UUID_16) {
   1385 
   1386             /* read include service UUID */
   1387             p_dev_cb->hid_srvc.incl_srvc_inst = incl_svc->handle;
   1388 
   1389             for (list_node_t *cn = list_begin(incl_svc->characteristics);
   1390                  cn != list_end(incl_svc->characteristics); cn = list_next(cn)) {
   1391                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
   1392                 if (p_char->uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL &&
   1393                     p_char->uuid.len == LEN_UUID_16) {
   1394 
   1395                     if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
   1396                                                           incl_svc->s_handle,
   1397                                                           GATT_UUID_BATTERY_LEVEL,
   1398                                                           p_char->handle) == NULL)
   1399                         APPL_TRACE_ERROR("Add battery report entry failed !!!");
   1400 
   1401                     gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
   1402                     return;
   1403                 }
   1404             }
   1405         }
   1406     }
   1407 
   1408     APPL_TRACE_ERROR("%s: Remote device does not have battery level", __func__);
   1409 }
   1410 
   1411 /*******************************************************************************
   1412 **
   1413 ** Function         bta_hh_le_search_hid_chars
   1414 **
   1415 ** Description      This function discover all characteristics a service and
   1416 **                  all descriptors available.
   1417 **
   1418 ** Parameters:
   1419 **
   1420 *******************************************************************************/
   1421 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service)
   1422 {
   1423     tBTA_HH_LE_RPT *p_rpt;
   1424 
   1425     for (list_node_t *cn = list_begin(service->characteristics);
   1426          cn != list_end(service->characteristics); cn = list_next(cn)) {
   1427         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
   1428 
   1429         if(p_char->uuid.len != LEN_UUID_16)
   1430             continue;
   1431 
   1432         LOG_DEBUG(LOG_TAG, "%s: %s 0x%04d", __func__, bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
   1433                   p_char->uuid.uu.uuid16);
   1434 
   1435         switch (p_char->uuid.uu.uuid16)
   1436         {
   1437         case GATT_UUID_HID_CONTROL_POINT:
   1438             p_dev_cb->hid_srvc.control_point_handle = p_char->handle;
   1439             break;
   1440         case GATT_UUID_HID_INFORMATION:
   1441         case GATT_UUID_HID_REPORT_MAP:
   1442             /* read the char value */
   1443             gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
   1444 
   1445             bta_hh_le_read_char_dscrpt(p_dev_cb, p_char->handle,
   1446                                    GATT_UUID_EXT_RPT_REF_DESCR);
   1447             break;
   1448 
   1449         case GATT_UUID_HID_REPORT:
   1450             p_rpt = bta_hh_le_find_alloc_report_entry(p_dev_cb,
   1451                                               p_dev_cb->hid_srvc.srvc_inst_id,
   1452                                               GATT_UUID_HID_REPORT,
   1453                                               p_char->handle);
   1454             if (p_rpt == NULL) {
   1455                 APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
   1456                 break;
   1457             }
   1458 
   1459             if (p_rpt->rpt_type != BTA_HH_RPTT_INPUT)
   1460                 break;
   1461 
   1462             bta_hh_le_read_char_dscrpt(p_dev_cb, p_char->handle, GATT_UUID_RPT_REF_DESCR);
   1463             break;
   1464 
   1465         /* found boot mode report types */
   1466         case GATT_UUID_HID_BT_KB_OUTPUT:
   1467         case GATT_UUID_HID_BT_MOUSE_INPUT:
   1468         case GATT_UUID_HID_BT_KB_INPUT:
   1469             if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
   1470                                       service->handle,
   1471                                       p_char->uuid.uu.uuid16,
   1472                                       p_char->handle) == NULL)
   1473                 APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
   1474 
   1475             break;
   1476 
   1477         default:
   1478             APPL_TRACE_DEBUG("%s: not processing %s 0x%04d", __func__,
   1479                              bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
   1480                              p_char->uuid.uu.uuid16);
   1481         }
   1482     }
   1483 
   1484     /* Make sure PROTO_MODE is processed as last */
   1485     for (list_node_t *cn = list_begin(service->characteristics);
   1486          cn != list_end(service->characteristics); cn = list_next(cn)) {
   1487         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
   1488 
   1489         if(p_char->uuid.len != LEN_UUID_16 &&
   1490            p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
   1491             p_dev_cb->hid_srvc.proto_mode_handle = p_char->handle;
   1492             bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
   1493             break;
   1494         }
   1495     }
   1496 }
   1497 
   1498 /*******************************************************************************
   1499 **
   1500 ** Function         bta_hh_le_srvc_search_cmpl
   1501 **
   1502 ** Description      This function process the GATT service search complete.
   1503 **
   1504 ** Parameters:
   1505 **
   1506 *******************************************************************************/
   1507 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
   1508 {
   1509     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   1510 
   1511     /* service search exception or no HID service is supported on remote */
   1512     if (p_dev_cb == NULL)
   1513         return;
   1514 
   1515     if(p_data->status != BTA_GATT_OK)
   1516     {
   1517         p_dev_cb->status = BTA_HH_ERR_SDP;
   1518         /* close the connection and report service discovery complete with error */
   1519         bta_hh_le_api_disc_act(p_dev_cb);
   1520         return;
   1521     }
   1522 
   1523     const list_t *services = BTA_GATTC_GetServices(p_data->conn_id);
   1524 
   1525     bool have_hid = false;
   1526     for (list_node_t *sn = list_begin(services);
   1527          sn != list_end(services); sn = list_next(sn)) {
   1528         tBTA_GATTC_SERVICE *service = list_node(sn);
   1529 
   1530         if (service->uuid.uu.uuid16 == UUID_SERVCLASS_LE_HID &&
   1531             service->is_primary && !have_hid) {
   1532             have_hid = true;
   1533 
   1534             /* found HID primamry service */
   1535             p_dev_cb->hid_srvc.in_use = TRUE;
   1536             p_dev_cb->hid_srvc.srvc_inst_id = service->handle;
   1537             p_dev_cb->hid_srvc.proto_mode_handle = 0;
   1538             p_dev_cb->hid_srvc.control_point_handle = 0;
   1539 
   1540             process_included(p_dev_cb, service);
   1541             bta_hh_le_search_hid_chars(p_dev_cb, service);
   1542 
   1543             APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc.srvc_inst_id);
   1544         } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_SCAN_PARAM) {
   1545             p_dev_cb->scan_refresh_char_handle = 0;
   1546 
   1547             for (list_node_t *cn = list_begin(service->characteristics);
   1548                  cn != list_end(service->characteristics); cn = list_next(cn)) {
   1549                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
   1550                 if (p_char->uuid.len == LEN_UUID_16 &&
   1551                     p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_REFRESH) {
   1552 
   1553                     p_dev_cb->scan_refresh_char_handle = p_char->handle;
   1554 
   1555                     if (p_char->properties & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
   1556                         p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
   1557                     else
   1558                         p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
   1559 
   1560                     break;
   1561                 }
   1562             }
   1563         } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER) {
   1564             //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
   1565             for (list_node_t *cn = list_begin(service->characteristics);
   1566                  cn != list_end(service->characteristics); cn = list_next(cn)) {
   1567                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
   1568                 if (p_char->uuid.len == LEN_UUID_16 &&
   1569                     p_char->uuid.uu.uuid16 == GATT_UUID_GAP_PREF_CONN_PARAM) {
   1570 
   1571                     /* read the char value */
   1572                     gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
   1573 
   1574                     break;
   1575                 }
   1576             }
   1577         }
   1578     }
   1579 
   1580     bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
   1581 }
   1582 
   1583 /*******************************************************************************
   1584 **
   1585 ** Function         bta_hh_read_battery_level_cmpl
   1586 **
   1587 ** Description      This function process the battery level read
   1588 **
   1589 ** Parameters:
   1590 **
   1591 *******************************************************************************/
   1592 void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1593 {
   1594     UNUSED(status);
   1595     UNUSED(p_data);
   1596     p_dev_cb->hid_srvc.expl_incl_srvc = TRUE;
   1597 }
   1598 
   1599 
   1600 /*******************************************************************************
   1601 **
   1602 ** Function         bta_hh_le_save_rpt_map
   1603 **
   1604 ** Description      save the report map into the control block.
   1605 **
   1606 ** Parameters:
   1607 **
   1608 *******************************************************************************/
   1609 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1610 {
   1611     tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc;
   1612 
   1613     osi_free_and_reset((void **)&p_srvc->rpt_map);
   1614 
   1615     if (p_data->p_value->len > 0)
   1616         p_srvc->rpt_map = (UINT8 *)osi_malloc(p_data->p_value->len);
   1617 
   1618     if (p_srvc->rpt_map != NULL)
   1619     {
   1620         UINT8 *pp = p_data->p_value->p_value;
   1621         STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->len);
   1622         p_srvc->descriptor.dl_len = p_data->p_value->len;
   1623         p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map;
   1624     }
   1625 }
   1626 
   1627 /*******************************************************************************
   1628 **
   1629 ** Function         bta_hh_le_proc_get_rpt_cmpl
   1630 **
   1631 ** Description      Process the Read report complete, send GET_REPORT_EVT to application
   1632 **                  with the report data.
   1633 **
   1634 ** Parameters:
   1635 **
   1636 *******************************************************************************/
   1637 void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1638 {
   1639     BT_HDR              *p_buf = NULL;
   1640     tBTA_HH_LE_RPT      *p_rpt;
   1641     tBTA_HH_HSDATA      hs_data;
   1642     UINT8               *pp ;
   1643 
   1644     if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
   1645     {
   1646         APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
   1647         return;
   1648     }
   1649 
   1650     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   1651                                                                           p_data->handle);
   1652 
   1653     memset(&hs_data, 0, sizeof(hs_data));
   1654     hs_data.status  = BTA_HH_ERR;
   1655     hs_data.handle  = p_dev_cb->hid_handle;
   1656 
   1657     if (p_data->status == BTA_GATT_OK)
   1658     {
   1659         p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   1660                                             p_char->service->handle,
   1661                                             p_char->uuid.uu.uuid16,
   1662                                             p_char->handle);
   1663 
   1664         if (p_rpt != NULL && p_data->p_value != NULL) {
   1665             p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + p_data->p_value->len + 1);
   1666             /* pack data send to app */
   1667             hs_data.status  = BTA_HH_OK;
   1668             p_buf->len = p_data->p_value->len + 1;
   1669             p_buf->layer_specific = 0;
   1670             p_buf->offset = 0;
   1671 
   1672             /* attach report ID as the first byte of the report before sending it to USB HID driver */
   1673             pp = (UINT8*)(p_buf + 1);
   1674             UINT8_TO_STREAM(pp, p_rpt->rpt_id);
   1675             memcpy(pp, p_data->p_value->p_value, p_data->p_value->len);
   1676 
   1677             hs_data.rsp_data.p_rpt_data =p_buf;
   1678         }
   1679     }
   1680 
   1681     p_dev_cb->w4_evt = 0;
   1682     (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
   1683 
   1684     osi_free_and_reset((void **)&p_buf);
   1685 }
   1686 
   1687 /*******************************************************************************
   1688 **
   1689 ** Function         bta_hh_le_proc_read_proto_mode
   1690 **
   1691 ** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
   1692 **                  with the protocol mode.
   1693 **
   1694 *******************************************************************************/
   1695 void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1696 {
   1697     tBTA_HH_HSDATA      hs_data;
   1698 
   1699     hs_data.status  = BTA_HH_ERR;
   1700     hs_data.handle  = p_dev_cb->hid_handle;
   1701     hs_data.rsp_data.proto_mode = p_dev_cb->mode;
   1702 
   1703     if (p_data->status == BTA_GATT_OK && p_data->p_value)
   1704     {
   1705         hs_data.status  = BTA_HH_OK;
   1706         /* match up BTE/BTA report/boot mode def*/
   1707         hs_data.rsp_data.proto_mode = *(p_data->p_value->p_value);
   1708         /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
   1709         if (hs_data.rsp_data.proto_mode == 0)
   1710             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
   1711         else
   1712             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
   1713 
   1714         p_dev_cb->mode = hs_data.rsp_data.proto_mode;
   1715     }
   1716 #if BTA_HH_DEBUG
   1717     APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
   1718                         (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
   1719 #endif
   1720 
   1721     p_dev_cb->w4_evt = 0;
   1722     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
   1723 
   1724 }
   1725 
   1726 /*******************************************************************************
   1727 **
   1728 ** Function         bta_hh_w4_le_read_char_cmpl
   1729 **
   1730 ** Description      process the GATT read complete in W4_CONN state.
   1731 **
   1732 ** Parameters:
   1733 **
   1734 *******************************************************************************/
   1735 void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1736 {
   1737     tBTA_GATTC_READ     * p_data = (tBTA_GATTC_READ *)p_buf;
   1738     UINT8               *pp ;
   1739 
   1740     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   1741                                                                           p_data->handle);
   1742     UINT16 char_uuid = p_char->uuid.uu.uuid16;
   1743 
   1744     if (char_uuid == GATT_UUID_BATTERY_LEVEL)
   1745     {
   1746         bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
   1747     }
   1748     else if (char_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
   1749     {
   1750         //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
   1751         UINT8 *pp = p_data->p_value->p_value;
   1752         UINT16 min, max, latency, tout;
   1753         STREAM_TO_UINT16 (min, pp);
   1754         STREAM_TO_UINT16 (max, pp);
   1755         STREAM_TO_UINT16 (latency, pp);
   1756         STREAM_TO_UINT16 (tout, pp);
   1757 
   1758         // Make sure both min, and max are bigger than 11.25ms, lower values can introduce
   1759         // audio issues if A2DP is also active.
   1760         if (min < BTM_BLE_CONN_INT_MIN_LIMIT)
   1761             min = BTM_BLE_CONN_INT_MIN_LIMIT;
   1762         if (max < BTM_BLE_CONN_INT_MIN_LIMIT)
   1763             max = BTM_BLE_CONN_INT_MIN_LIMIT;
   1764 
   1765         if (tout < BTM_BLE_CONN_TIMEOUT_MIN_DEF)
   1766             tout = BTM_BLE_CONN_TIMEOUT_MIN_DEF;
   1767 
   1768         BTM_BleSetPrefConnParams (p_dev_cb->addr, min, max, latency, tout);
   1769         L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
   1770     }
   1771     else
   1772     {
   1773         if (p_data->status == BTA_GATT_OK && p_data->p_value)
   1774         {
   1775             pp = p_data->p_value->p_value;
   1776 
   1777             switch (char_uuid)
   1778             {
   1779            /* save device information */
   1780             case GATT_UUID_HID_INFORMATION:
   1781                 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
   1782                 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
   1783                 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
   1784                 break;
   1785 
   1786             case GATT_UUID_HID_REPORT_MAP:
   1787                 bta_hh_le_save_rpt_map(p_dev_cb, p_data);
   1788                 return;
   1789 
   1790             default:
   1791 #if BTA_HH_DEBUG == TRUE
   1792                 APPL_TRACE_ERROR("Unexpected read %s(0x%04x)",
   1793                                 bta_hh_uuid_to_str(char_uuid), char_uuid);
   1794 #endif
   1795                 break;
   1796             }
   1797         }
   1798         else
   1799         {
   1800 #if BTA_HH_DEBUG == TRUE
   1801             APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d", bta_hh_uuid_to_str(char_uuid),
   1802                              char_uuid, p_data->status);
   1803 #else
   1804             APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", char_uuid, p_data->status);
   1805 #endif
   1806         }
   1807     }
   1808 
   1809 }
   1810 
   1811 /*******************************************************************************
   1812 **
   1813 ** Function         bta_hh_le_read_char_cmpl
   1814 **
   1815 ** Description      a characteristic value is received.
   1816 **
   1817 ** Parameters:
   1818 **
   1819 *******************************************************************************/
   1820 void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1821 {
   1822     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   1823 
   1824     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   1825                                                                           p_data->handle);
   1826     UINT16 char_uuid = p_char->uuid.uu.uuid16;
   1827 
   1828     switch (char_uuid)
   1829     {
   1830     /* GET_REPORT */
   1831     case GATT_UUID_HID_REPORT:
   1832     case GATT_UUID_HID_BT_KB_INPUT:
   1833     case GATT_UUID_HID_BT_KB_OUTPUT:
   1834     case GATT_UUID_HID_BT_MOUSE_INPUT:
   1835     case GATT_UUID_BATTERY_LEVEL: /* read battery level */
   1836         bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
   1837         break;
   1838 
   1839     case GATT_UUID_HID_PROTO_MODE:
   1840         bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
   1841         break;
   1842 
   1843     default:
   1844         APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", char_uuid);
   1845         break;
   1846     }
   1847 
   1848 }
   1849 
   1850 /*******************************************************************************
   1851 **
   1852 ** Function         bta_hh_le_read_descr_cmpl
   1853 **
   1854 ** Description      read characteristic descriptor is completed in CONN st.
   1855 **
   1856 ** Parameters:
   1857 **
   1858 *******************************************************************************/
   1859 void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1860 {
   1861     tBTA_HH_LE_RPT  *p_rpt;
   1862     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   1863     UINT8   *pp;
   1864 
   1865     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
   1866 
   1867     /* if a report client configuration */
   1868     if (p_desc->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
   1869     {
   1870         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   1871                                                  p_desc->characteristic->service->handle,
   1872                                                  p_desc->characteristic->uuid.uu.uuid16,
   1873                                                  p_desc->characteristic->handle)) != NULL)
   1874         {
   1875             pp = p_data->p_value->p_value;
   1876             STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
   1877 
   1878             APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
   1879         }
   1880     }
   1881 }
   1882 
   1883 /*******************************************************************************
   1884 **
   1885 ** Function         bta_hh_w4_le_read_descr_cmpl
   1886 **
   1887 ** Description      read characteristic descriptor is completed in W4_CONN st.
   1888 **
   1889 ** Parameters:
   1890 **
   1891 *******************************************************************************/
   1892 void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1893 {
   1894     tBTA_HH_LE_RPT  *p_rpt;
   1895     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   1896     UINT16 char_uuid16;
   1897 
   1898     if (p_data == NULL)
   1899         return;
   1900 
   1901     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
   1902 
   1903     if (p_desc == NULL) {
   1904         APPL_TRACE_ERROR("%s: p_descr is NULL %d", __func__, p_data->handle);
   1905         return;
   1906     }
   1907 
   1908     char_uuid16 = p_desc->characteristic->uuid.uu.uuid16;
   1909 
   1910 #if BTA_HH_DEBUG == TRUE
   1911     APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
   1912                         bta_hh_uuid_to_str(p_desc->uuid.uu.uuid16),
   1913                         p_desc->uuid.uu.uuid16);
   1914 #endif
   1915     switch (char_uuid16)
   1916     {
   1917     case GATT_UUID_HID_REPORT:
   1918         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   1919                                             p_desc->characteristic->service->handle,
   1920                                             GATT_UUID_HID_REPORT,
   1921                                             p_desc->characteristic->handle)))
   1922             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
   1923         break;
   1924 
   1925     case GATT_UUID_HID_REPORT_MAP:
   1926         bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
   1927         break;
   1928 
   1929     case GATT_UUID_BATTERY_LEVEL:
   1930         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   1931                                             p_desc->characteristic->service->handle,
   1932                                             GATT_UUID_BATTERY_LEVEL,
   1933                                             p_desc->characteristic->handle)))
   1934             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
   1935 
   1936         break;
   1937 
   1938     default:
   1939         APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
   1940         break;
   1941     }
   1942 }
   1943 
   1944 /*******************************************************************************
   1945 **
   1946 ** Function         bta_hh_w4_le_write_cmpl
   1947 **
   1948 ** Description      Write charactersitic complete event at W4_CONN st.
   1949 **
   1950 ** Parameters:
   1951 **
   1952 *******************************************************************************/
   1953 void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1954 {
   1955     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   1956 
   1957     if (p_data == NULL)
   1958         return;
   1959 
   1960     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   1961                                                                           p_data->handle);
   1962 
   1963     if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
   1964     {
   1965         p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
   1966 
   1967         if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) == 0)
   1968             bta_hh_le_open_cmpl(p_dev_cb);
   1969     }
   1970 }
   1971 
   1972 /*******************************************************************************
   1973 **
   1974 ** Function         bta_hh_le_write_cmpl
   1975 **
   1976 ** Description      Write charactersitic complete event at CONN st.
   1977 **
   1978 ** Parameters:
   1979 **
   1980 *******************************************************************************/
   1981 void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1982 {
   1983     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   1984     tBTA_HH_CBDATA      cback_data ;
   1985     UINT16              cb_evt = p_dev_cb->w4_evt;
   1986 
   1987     if (p_data == NULL  || cb_evt == 0)
   1988         return;
   1989 
   1990     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   1991                                                                           p_data->handle);
   1992 
   1993 #if BTA_HH_DEBUG
   1994     APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
   1995 #endif
   1996     switch (p_char->uuid.uu.uuid16)
   1997     {
   1998     /* Set protocol finished */
   1999     case GATT_UUID_HID_PROTO_MODE:
   2000         cback_data.handle  = p_dev_cb->hid_handle;
   2001         if (p_data->status == BTA_GATT_OK)
   2002         {
   2003             bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, FALSE);
   2004             cback_data.status = BTA_HH_OK;
   2005         }
   2006         else
   2007             cback_data.status =  BTA_HH_ERR;
   2008         p_dev_cb->w4_evt = 0;
   2009         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   2010         break;
   2011 
   2012     /* Set Report finished */
   2013     case GATT_UUID_HID_REPORT:
   2014     case GATT_UUID_HID_BT_KB_INPUT:
   2015     case GATT_UUID_HID_BT_MOUSE_INPUT:
   2016     case GATT_UUID_HID_BT_KB_OUTPUT:
   2017         cback_data.handle  = p_dev_cb->hid_handle;
   2018         cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
   2019         p_dev_cb->w4_evt = 0;
   2020         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   2021         break;
   2022 
   2023     case GATT_UUID_SCAN_INT_WINDOW:
   2024         bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
   2025         break;
   2026 
   2027     default:
   2028         break;
   2029     }
   2030 
   2031 }
   2032 
   2033 /*******************************************************************************
   2034 **
   2035 ** Function         bta_hh_le_write_char_descr_cmpl
   2036 **
   2037 ** Description      Write charactersitic descriptor complete event
   2038 **
   2039 ** Parameters:
   2040 **
   2041 *******************************************************************************/
   2042 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2043 {
   2044     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   2045     UINT8   srvc_inst_id, hid_inst_id;
   2046 
   2047     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_dev_cb->conn_id,
   2048                                                                        p_data->handle);
   2049 
   2050     UINT16 desc_uuid = p_desc->uuid.uu.uuid16;
   2051     UINT16 char_uuid = p_desc->characteristic->uuid.uu.uuid16;
   2052     /* only write client configuration possible */
   2053     if (desc_uuid == GATT_UUID_CHAR_CLIENT_CONFIG)
   2054     {
   2055         srvc_inst_id = p_desc->characteristic->service->handle;
   2056         hid_inst_id = srvc_inst_id;
   2057         switch (char_uuid)
   2058         {
   2059         case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
   2060             hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
   2061             /* fall through */
   2062         case GATT_UUID_HID_BT_KB_INPUT:
   2063         case GATT_UUID_HID_BT_MOUSE_INPUT:
   2064         case GATT_UUID_HID_REPORT:
   2065             if (p_data->status == BTA_GATT_OK)
   2066                 p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
   2067                         BTA_GATT_CLT_CONFIG_NOTIFICATION;
   2068             p_dev_cb->clt_cfg_idx ++;
   2069             bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
   2070 
   2071             break;
   2072 
   2073         case GATT_UUID_SCAN_REFRESH:
   2074             bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
   2075             break;
   2076 
   2077         default:
   2078             APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", char_uuid);
   2079         }
   2080     }
   2081     else
   2082     {
   2083 #if BTA_HH_DEBUG == TRUE
   2084         APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)",
   2085                          bta_hh_uuid_to_str(desc_uuid), desc_uuid);
   2086 #else
   2087         APPL_TRACE_ERROR("Unexpected write to (0x%04x)", desc_uuid);
   2088 #endif
   2089     }
   2090 
   2091 }
   2092 
   2093 /*******************************************************************************
   2094 **
   2095 ** Function         bta_hh_le_input_rpt_notify
   2096 **
   2097 ** Description      process the notificaton event, most likely for input report.
   2098 **
   2099 ** Parameters:
   2100 **
   2101 *******************************************************************************/
   2102 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
   2103 {
   2104     tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   2105     UINT8           app_id;
   2106     UINT8           *p_buf;
   2107     tBTA_HH_LE_RPT  *p_rpt;
   2108 
   2109     if (p_dev_cb == NULL)
   2110     {
   2111         APPL_TRACE_ERROR("notification received from Unknown device");
   2112         return;
   2113     }
   2114 
   2115     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
   2116                                                                           p_data->handle);
   2117 
   2118     app_id= p_dev_cb->app_id;
   2119 
   2120     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   2121                                         p_dev_cb->hid_srvc.srvc_inst_id,
   2122                                         p_char->uuid.uu.uuid16,
   2123                                         p_char->handle);
   2124     if (p_rpt == NULL)
   2125     {
   2126         APPL_TRACE_ERROR("notification received for Unknown Report");
   2127         return;
   2128     }
   2129 
   2130     if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
   2131         app_id = BTA_HH_APP_ID_MI;
   2132     else if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
   2133         app_id = BTA_HH_APP_ID_KB;
   2134 
   2135     APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
   2136 
   2137     /* need to append report ID to the head of data */
   2138     if (p_rpt->rpt_id != 0)
   2139     {
   2140         p_buf = (UINT8 *)osi_malloc(p_data->len + 1);
   2141 
   2142         p_buf[0] = p_rpt->rpt_id;
   2143         memcpy(&p_buf[1], p_data->value, p_data->len);
   2144         ++p_data->len;
   2145     } else {
   2146         p_buf = p_data->value;
   2147     }
   2148 
   2149     bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
   2150                     p_buf,
   2151                     p_data->len,
   2152                     p_dev_cb->mode,
   2153                     0 , /* no sub class*/
   2154                     p_dev_cb->dscp_info.ctry_code,
   2155                     p_dev_cb->addr,
   2156                     app_id);
   2157 
   2158     if (p_buf != p_data->value)
   2159         osi_free(p_buf);
   2160 }
   2161 
   2162 /*******************************************************************************
   2163 **
   2164 ** Function         bta_hh_gatt_open_fail
   2165 **
   2166 ** Description      action function to process the open fail
   2167 **
   2168 ** Returns          void
   2169 **
   2170 *******************************************************************************/
   2171 void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2172 {
   2173     tBTA_HH_CONN            conn_dat ;
   2174 
   2175     /* open failure in the middle of service discovery, clear all services */
   2176     if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS)
   2177     {
   2178         bta_hh_clear_service_cache(p_cb);
   2179     }
   2180 
   2181     p_cb->disc_active = BTA_HH_LE_DISC_NONE;
   2182     /* Failure in opening connection or GATT discovery failure */
   2183     conn_dat.handle = p_cb->hid_handle;
   2184     memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
   2185     conn_dat.le_hid = TRUE;
   2186     conn_dat.scps_supported = p_cb->scps_supported;
   2187 
   2188     if (p_cb->status == BTA_HH_OK)
   2189         conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
   2190     else
   2191         conn_dat.status = p_cb->status;
   2192 
   2193     /* Report OPEN fail event */
   2194     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
   2195 
   2196 }
   2197 
   2198 /*******************************************************************************
   2199 **
   2200 ** Function         bta_hh_gatt_close
   2201 **
   2202 ** Description      action function to process the GATT close int he state machine.
   2203 **
   2204 ** Returns          void
   2205 **
   2206 *******************************************************************************/
   2207 void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2208 {
   2209     tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
   2210 
   2211     /* finaliza device driver */
   2212     bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
   2213     /* update total conn number */
   2214     bta_hh_cb.cnt_num --;
   2215 
   2216     disc_dat.handle = p_cb->hid_handle;
   2217     disc_dat.status = p_cb->status;
   2218 
   2219     (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
   2220 
   2221     /* if no connection is active and HH disable is signaled, disable service */
   2222     if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
   2223     {
   2224         bta_hh_disc_cmpl();
   2225     }
   2226     else
   2227     {
   2228 #if (BTA_HH_LE_RECONN == TRUE)
   2229     if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
   2230     {
   2231         bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
   2232     }
   2233 #endif
   2234     }
   2235 
   2236     return;
   2237 
   2238 }
   2239 
   2240 /*******************************************************************************
   2241 **
   2242 ** Function         bta_hh_le_api_disc_act
   2243 **
   2244 ** Description      initaite a Close API to a remote HID device
   2245 **
   2246 ** Returns          void
   2247 **
   2248 *******************************************************************************/
   2249 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
   2250 {
   2251     if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
   2252     {
   2253         gatt_op_queue_clean(p_cb->conn_id);
   2254         BTA_GATTC_Close(p_cb->conn_id);
   2255         /* remove device from background connection if intended to disconnect,
   2256            do not allow reconnection */
   2257         bta_hh_le_remove_dev_bg_conn(p_cb);
   2258     }
   2259 }
   2260 
   2261 /*******************************************************************************
   2262 **
   2263 ** Function         bta_hh_le_get_rpt
   2264 **
   2265 ** Description      GET_REPORT on a LE HID Report
   2266 **
   2267 ** Returns          void
   2268 **
   2269 *******************************************************************************/
   2270 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
   2271 {
   2272     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);
   2273 
   2274     if (p_rpt == NULL) {
   2275         APPL_TRACE_ERROR("%s: no matching report", __func__);
   2276         return;
   2277     }
   2278 
   2279     p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
   2280     gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_rpt->char_inst_id);
   2281 }
   2282 
   2283 /*******************************************************************************
   2284 **
   2285 ** Function         bta_hh_le_write_rpt
   2286 **
   2287 ** Description      SET_REPORT/or DATA output on a LE HID Report
   2288 **
   2289 ** Returns          void
   2290 **
   2291 *******************************************************************************/
   2292 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb,
   2293                          tBTA_HH_RPT_TYPE r_type,
   2294                          BT_HDR *p_buf, UINT16 w4_evt )
   2295 {
   2296     tBTA_HH_LE_RPT  *p_rpt;
   2297     UINT8   *p_value, rpt_id;
   2298 
   2299     if (p_buf == NULL || p_buf->len == 0)
   2300     {
   2301         APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data");
   2302         return;
   2303     }
   2304 
   2305     /* strip report ID from the data */
   2306     p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
   2307     STREAM_TO_UINT8(rpt_id, p_value);
   2308     p_buf->len -= 1;
   2309 
   2310     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
   2311 
   2312     if (p_rpt == NULL) {
   2313         APPL_TRACE_ERROR("%s: no matching report", __func__);
   2314         osi_free(p_buf);
   2315         return;
   2316     }
   2317 
   2318     p_cb->w4_evt = w4_evt;
   2319 
   2320     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_cb->conn_id,
   2321                                                                           p_rpt->char_inst_id);
   2322 
   2323     tBTA_GATTC_WRITE_TYPE write_type = BTA_GATTC_TYPE_WRITE;
   2324     if (p_char && (p_char->properties & BTA_GATT_CHAR_PROP_BIT_WRITE_NR))
   2325         write_type = BTA_GATTC_TYPE_WRITE_NO_RSP;
   2326 
   2327     gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
   2328                         p_buf->len, p_value, write_type);
   2329 }
   2330 
   2331 /*******************************************************************************
   2332 **
   2333 ** Function         bta_hh_le_suspend
   2334 **
   2335 ** Description      send LE suspend or exit suspend mode to remote device.
   2336 **
   2337 ** Returns          void
   2338 **
   2339 *******************************************************************************/
   2340 void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
   2341 {
   2342     ctrl_type -= BTA_HH_CTRL_SUSPEND;
   2343 
   2344     gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.control_point_handle, 1,
   2345                         &ctrl_type, BTA_GATTC_TYPE_WRITE_NO_RSP);
   2346 }
   2347 
   2348 /*******************************************************************************
   2349 **
   2350 ** Function         bta_hh_le_write_dev_act
   2351 **
   2352 ** Description      Write LE device action. can be SET/GET/DATA transaction.
   2353 **
   2354 ** Returns          void
   2355 **
   2356 *******************************************************************************/
   2357 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2358 {
   2359     switch(p_data->api_sndcmd.t_type)
   2360     {
   2361         case HID_TRANS_SET_PROTOCOL:
   2362             p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
   2363             bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
   2364             break;
   2365 
   2366         case HID_TRANS_GET_PROTOCOL:
   2367             bta_hh_le_get_protocol_mode(p_cb);
   2368             break;
   2369 
   2370         case HID_TRANS_GET_REPORT:
   2371             bta_hh_le_get_rpt(p_cb,
   2372                               p_data->api_sndcmd.param,
   2373                               p_data->api_sndcmd.rpt_id);
   2374             break;
   2375 
   2376         case HID_TRANS_SET_REPORT:
   2377             bta_hh_le_write_rpt(p_cb,
   2378                                 p_data->api_sndcmd.param,
   2379                                 p_data->api_sndcmd.p_data,
   2380                                 BTA_HH_SET_RPT_EVT);
   2381             break;
   2382 
   2383         case HID_TRANS_DATA:  /* output report */
   2384 
   2385             bta_hh_le_write_rpt(p_cb,
   2386                                 p_data->api_sndcmd.param,
   2387                                 p_data->api_sndcmd.p_data,
   2388                                 BTA_HH_DATA_EVT);
   2389             break;
   2390 
   2391         case HID_TRANS_CONTROL:
   2392             /* no handshake event will be generated */
   2393             /* if VC_UNPLUG is issued, set flag */
   2394             if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
   2395                 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
   2396             {
   2397                 bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
   2398             }
   2399             break;
   2400 
   2401         default:
   2402             APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
   2403                 __func__, p_data->api_sndcmd.t_type);
   2404             break;
   2405     }
   2406 }
   2407 
   2408 /*******************************************************************************
   2409 **
   2410 ** Function         bta_hh_le_get_dscp_act
   2411 **
   2412 ** Description      Send ReportDescriptor to application for all HID services.
   2413 **
   2414 ** Returns          void
   2415 **
   2416 *******************************************************************************/
   2417 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
   2418 {
   2419     if (p_cb->hid_srvc.in_use)
   2420     {
   2421         p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len;
   2422         p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list;
   2423 
   2424         (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
   2425     }
   2426 }
   2427 
   2428 /*******************************************************************************
   2429 **
   2430 ** Function         bta_hh_le_add_dev_bg_conn
   2431 **
   2432 ** Description      Remove a LE HID device from back ground connection procedure.
   2433 **
   2434 ** Returns          void
   2435 **
   2436 *******************************************************************************/
   2437 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
   2438 {
   2439     UINT8           sec_flag=0;
   2440     BOOLEAN         to_add = TRUE;
   2441 
   2442     if (check_bond)
   2443     {
   2444         /* start reconnection if remote is a bonded device */
   2445         /* verify bond */
   2446         BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   2447 
   2448         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
   2449             to_add = FALSE;
   2450     }
   2451 
   2452     if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
   2453         !p_cb->in_bg_conn && to_add)
   2454     {
   2455         /* add device into BG connection to accept remote initiated connection */
   2456         BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
   2457         p_cb->in_bg_conn = TRUE;
   2458 
   2459         BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
   2460     }
   2461     return;
   2462 }
   2463 
   2464 /*******************************************************************************
   2465 **
   2466 ** Function         bta_hh_le_add_device
   2467 **
   2468 ** Description      Add a LE HID device as a known device, and also add the address
   2469 **                  into back ground connection WL for incoming connection.
   2470 **
   2471 ** Returns          void
   2472 **
   2473 *******************************************************************************/
   2474 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
   2475 {
   2476     p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
   2477     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   2478 
   2479     /* update DI information */
   2480     bta_hh_update_di_info(p_cb,
   2481                           p_dev_info->dscp_info.vendor_id,
   2482                           p_dev_info->dscp_info.product_id,
   2483                           p_dev_info->dscp_info.version,
   2484                           p_dev_info->dscp_info.flag);
   2485 
   2486     /* add to BTA device list */
   2487     bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
   2488                               p_dev_info->attr_mask,
   2489                               &p_dev_info->dscp_info.descriptor,
   2490                               p_dev_info->sub_class,
   2491                               p_dev_info->dscp_info.ssr_max_latency,
   2492                               p_dev_info->dscp_info.ssr_min_tout,
   2493                               p_dev_info->app_id);
   2494 
   2495     bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
   2496 
   2497     return p_cb->hid_handle;
   2498 }
   2499 
   2500 /*******************************************************************************
   2501 **
   2502 ** Function         bta_hh_le_remove_dev_bg_conn
   2503 **
   2504 ** Description      Remove a LE HID device from back ground connection procedure.
   2505 **
   2506 ** Returns          void
   2507 **
   2508 *******************************************************************************/
   2509 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
   2510 {
   2511     if (p_dev_cb->in_bg_conn)
   2512     {
   2513         p_dev_cb->in_bg_conn = FALSE;
   2514 
   2515         BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
   2516     }
   2517 }
   2518 
   2519 /*******************************************************************************
   2520 **
   2521 ** Function         bta_hh_le_update_scpp
   2522 **
   2523 ** Description      action function to update the scan parameters on remote HID
   2524 **                  device
   2525 **
   2526 ** Parameters:
   2527 **
   2528 *******************************************************************************/
   2529 void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2530 {
   2531     UINT8   value[4], *p = value;
   2532     tBTA_HH_CBDATA      cback_data;
   2533 
   2534     if (!p_dev_cb->is_le_device ||
   2535         p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
   2536         p_dev_cb->scps_supported == FALSE) {
   2537         APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP ");
   2538 
   2539         cback_data.handle = p_dev_cb->hid_handle;
   2540         cback_data.status = BTA_HH_ERR;
   2541         (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
   2542 
   2543         return;
   2544     }
   2545 
   2546     p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
   2547 
   2548     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
   2549     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
   2550 
   2551     gatt_queue_write_op(GATT_WRITE_CHAR, p_dev_cb->conn_id, p_dev_cb->scan_refresh_char_handle, 2,
   2552                         value, BTA_GATTC_TYPE_WRITE_NO_RSP);
   2553 }
   2554 
   2555 /*******************************************************************************
   2556 **
   2557 ** Function         bta_hh_gattc_callback
   2558 **
   2559 ** Description      This is GATT client callback function used in BTA HH.
   2560 **
   2561 ** Parameters:
   2562 **
   2563 *******************************************************************************/
   2564 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
   2565 {
   2566     tBTA_HH_DEV_CB *p_dev_cb;
   2567     UINT16          evt;
   2568 #if BTA_HH_DEBUG
   2569     APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
   2570 #endif
   2571     if (p_data == NULL)
   2572         return;
   2573 
   2574     switch (event)
   2575     {
   2576         case BTA_GATTC_REG_EVT: /* 0 */
   2577             bta_hh_le_register_cmpl(&p_data->reg_oper);
   2578             break;
   2579 
   2580         case BTA_GATTC_DEREG_EVT: /* 1 */
   2581             bta_hh_cleanup_disable(p_data->reg_oper.status);
   2582             break;
   2583 
   2584         case BTA_GATTC_OPEN_EVT: /* 2 */
   2585             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
   2586             if (p_dev_cb) {
   2587                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
   2588             }
   2589             break;
   2590 
   2591         case BTA_GATTC_READ_CHAR_EVT: /* 3 */
   2592         case BTA_GATTC_READ_DESCR_EVT: /* 8 */
   2593             mark_as_not_executing(p_data->read.conn_id);
   2594             gatt_execute_next_op(p_data->read.conn_id);
   2595             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
   2596             if (event == BTA_GATTC_READ_CHAR_EVT)
   2597                 evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
   2598             else
   2599                 evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
   2600 
   2601             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
   2602             break;
   2603 
   2604         case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
   2605         case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
   2606             mark_as_not_executing(p_data->write.conn_id);
   2607             gatt_execute_next_op(p_data->write.conn_id);
   2608             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
   2609             if (event == BTA_GATTC_WRITE_CHAR_EVT)
   2610                 evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
   2611             else
   2612                 evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
   2613 
   2614             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
   2615             break;
   2616 
   2617         case BTA_GATTC_CLOSE_EVT: /* 5 */
   2618             bta_hh_le_close(&p_data->close);
   2619             break;
   2620 
   2621         case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
   2622             bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
   2623             break;
   2624 
   2625         case BTA_GATTC_NOTIF_EVT: /* 10 */
   2626             bta_hh_le_input_rpt_notify(&p_data->notify);
   2627             break;
   2628 
   2629         case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
   2630             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
   2631             if (p_dev_cb) {
   2632                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
   2633                               (tBTA_HH_DATA *)&p_data->enc_cmpl);
   2634             }
   2635             break;
   2636 
   2637         default:
   2638             break;
   2639     }
   2640 }
   2641 
   2642 /*******************************************************************************
   2643 **
   2644 ** Function         bta_hh_le_hid_read_rpt_clt_cfg
   2645 **
   2646 ** Description      a test command to read report descriptor client configuration
   2647 **
   2648 ** Returns          void
   2649 **
   2650 *******************************************************************************/
   2651 void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
   2652 {
   2653     tBTA_HH_DEV_CB *p_cb = NULL;
   2654     tBTA_HH_LE_RPT *p_rpt ;
   2655     UINT8           index = BTA_HH_IDX_INVALID;
   2656 
   2657     index = bta_hh_find_cb(bd_addr);
   2658     if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
   2659     {
   2660         APPL_TRACE_ERROR("unknown device");
   2661         return;
   2662     }
   2663 
   2664     p_cb = &bta_hh_cb.kdev[index];
   2665 
   2666     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
   2667 
   2668     if (p_rpt == NULL)
   2669     {
   2670         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
   2671         return;
   2672     }
   2673 
   2674     bta_hh_le_read_char_dscrpt(p_cb, p_rpt->char_inst_id, GATT_UUID_CHAR_CLIENT_CONFIG);
   2675     return;
   2676 }
   2677 
   2678 /*******************************************************************************
   2679 **
   2680 ** Function         bta_hh_le_register_scpp_notif
   2681 **
   2682 ** Description      register scan parameter refresh notitication complete
   2683 **
   2684 **
   2685 ** Parameters:
   2686 **
   2687 *******************************************************************************/
   2688 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
   2689 {
   2690     UINT8               sec_flag=0;
   2691 
   2692     /* if write scan parameter sucessful */
   2693     /* if bonded and notification is not enabled, configure the client configuration */
   2694     if (status == BTA_GATT_OK &&
   2695         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
   2696         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
   2697     {
   2698         BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   2699         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
   2700         {
   2701             if (bta_hh_le_write_char_clt_cfg (p_dev_cb, p_dev_cb->scan_refresh_char_handle,
   2702                                               BTA_GATT_CLT_CONFIG_NOTIFICATION))
   2703             {
   2704                 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
   2705                                                    p_dev_cb->scan_refresh_char_handle);
   2706                 return;
   2707             }
   2708         }
   2709     }
   2710     bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
   2711 }
   2712 
   2713 /*******************************************************************************
   2714 **
   2715 ** Function         bta_hh_le_register_scpp_notif_cmpl
   2716 **
   2717 ** Description      action function to register scan parameter refresh notitication
   2718 **
   2719 ** Parameters:
   2720 **
   2721 *******************************************************************************/
   2722 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
   2723 {
   2724     tBTA_HH_CBDATA      cback_data ;
   2725     UINT16              cb_evt = p_dev_cb->w4_evt;
   2726 
   2727     if (status == BTA_GATT_OK)
   2728         p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
   2729 
   2730     cback_data.handle = p_dev_cb->hid_handle;
   2731     cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
   2732     p_dev_cb->w4_evt = 0;
   2733     (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   2734 }
   2735 
   2736 /*******************************************************************************
   2737 **
   2738 ** Function         bta_hh_process_cache_rpt
   2739 **
   2740 ** Description      Process the cached reports
   2741 **
   2742 ** Parameters:
   2743 **
   2744 *******************************************************************************/
   2745 //TODO(jpawlowski): uncomment when fixed
   2746 // static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
   2747 //                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
   2748 //                                       UINT8 num_rpt)
   2749 // {
   2750 //     UINT8                       i = 0;
   2751 //     tBTA_HH_LE_RPT              *p_rpt;
   2752 
   2753 //     if (num_rpt != 0)  /* no cache is found */
   2754 //     {
   2755 //         p_cb->hid_srvc.in_use = TRUE;
   2756 
   2757 //         /* set the descriptor info */
   2758 //         p_cb->hid_srvc.descriptor.dl_len =
   2759 //                 p_cb->dscp_info.descriptor.dl_len;
   2760 //         p_cb->hid_srvc.descriptor.dsc_list =
   2761 //                     p_cb->dscp_info.descriptor.dsc_list;
   2762 
   2763 //         for (; i <num_rpt; i ++, p_rpt_cache ++)
   2764 //         {
   2765 //             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
   2766 //                                                p_rpt_cache->srvc_inst_id,
   2767 //                                                p_rpt_cache->rpt_uuid,
   2768 //                                                p_rpt_cache->char_inst_id,
   2769 //                                                p_rpt_cache->prop))  == NULL)
   2770 //             {
   2771 //                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
   2772 //                 break;
   2773 //             }
   2774 //             else
   2775 //             {
   2776 //                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
   2777 //                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
   2778 
   2779 //                 if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
   2780 //                     p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
   2781 //                     (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
   2782 //                 {
   2783 //                     p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
   2784 //                 }
   2785 //             }
   2786 //         }
   2787 //     }
   2788 // }
   2789 
   2790 #endif
   2791 
   2792 
   2793 
   2794 
   2795