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