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