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