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