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 
   1269     bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1270 }
   1271 
   1272 /*******************************************************************************
   1273 **
   1274 ** Function         bta_hh_security_cmpl
   1275 **
   1276 ** Description      Security check completed, start the service discovery
   1277 **                  if no cache available, otherwise report connection open completed
   1278 **
   1279 ** Parameters:
   1280 **
   1281 *******************************************************************************/
   1282 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1283 {
   1284     tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
   1285     UINT8                       num_rpt = 0;
   1286     UNUSED(p_buf);
   1287 
   1288     if (p_cb->status == BTA_HH_OK)
   1289     {
   1290         APPL_TRACE_DEBUG("bta_hh_security_cmpl OK");
   1291         if (!p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
   1292         {
   1293             APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
   1294             /* start loading the cache if not in stack */
   1295             if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
   1296             {
   1297                 bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
   1298             }
   1299         }
   1300         /*  discovery has been done for HID service */
   1301         if (p_cb->app_id != 0 && p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
   1302         {
   1303             /* configure protocol mode */
   1304             if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE)
   1305             {
   1306                 APPL_TRACE_ERROR("bta_hh_security_cmpl");
   1307                 bta_hh_le_open_cmpl(p_cb);
   1308             }
   1309         }
   1310         /* start primary service discovery for HID service */
   1311         else
   1312         {
   1313             bta_hh_le_pri_service_discovery(p_cb);
   1314         }
   1315     }
   1316     else
   1317         bta_hh_le_api_disc_act(p_cb);
   1318 
   1319 }
   1320 
   1321 /*******************************************************************************
   1322 **
   1323 ** Function         bta_hh_le_notify_enc_cmpl
   1324 **
   1325 ** Description      process GATT encryption complete event
   1326 **
   1327 ** Returns
   1328 **
   1329 *******************************************************************************/
   1330 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1331 {
   1332     if (p_cb == NULL || p_cb->security_pending == FALSE ||
   1333         p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
   1334     {
   1335         return;
   1336     }
   1337 
   1338     p_cb->security_pending = FALSE;
   1339     bta_hh_start_security(p_cb, NULL);
   1340 }
   1341 
   1342 /*******************************************************************************
   1343 **
   1344 ** Function         bta_hh_clear_service_cache
   1345 **
   1346 ** Description      clear the service cache
   1347 **
   1348 ** Parameters:
   1349 **
   1350 *******************************************************************************/
   1351 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
   1352 {
   1353     UINT8 i;
   1354     tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc[0];
   1355 
   1356     p_cb->app_id = 0;
   1357     p_cb->total_srvc = 0;
   1358     p_cb->dscp_info.descriptor.dsc_list = NULL;
   1359 
   1360     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++)
   1361     {
   1362         utl_freebuf((void **)&p_hid_srvc->rpt_map);
   1363         memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
   1364     }
   1365 }
   1366 
   1367 /*******************************************************************************
   1368 **
   1369 ** Function         bta_hh_start_security
   1370 **
   1371 ** Description      start the security check of the established connection
   1372 **
   1373 ** Parameters:
   1374 **
   1375 *******************************************************************************/
   1376 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1377 {
   1378     UINT8           sec_flag=0;
   1379     tBTM_SEC_DEV_REC  *p_dev_rec;
   1380     UNUSED(p_buf);
   1381 
   1382     p_dev_rec = btm_find_dev(p_cb->addr);
   1383     if (p_dev_rec)
   1384     {
   1385         if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
   1386             p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
   1387         {
   1388             /* if security collision happened, wait for encryption done */
   1389             p_cb->security_pending = TRUE;
   1390             return;
   1391         }
   1392     }
   1393 
   1394     /* verify bond */
   1395     BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   1396 
   1397     /* if link has been encrypted */
   1398     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
   1399     {
   1400         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1401     }
   1402     /* if bonded and link not encrypted */
   1403     else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
   1404     {
   1405         sec_flag = BTM_BLE_SEC_ENCRYPT;
   1406         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1407         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
   1408     }
   1409     /* unbonded device, report security error here */
   1410     else if (p_cb->sec_mask != BTA_SEC_NONE)
   1411     {
   1412         sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
   1413         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
   1414         bta_hh_clear_service_cache(p_cb);
   1415         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
   1416     }
   1417     /* otherwise let it go through */
   1418     else
   1419     {
   1420         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
   1421     }
   1422 
   1423 
   1424 }
   1425 
   1426 /*******************************************************************************
   1427 **
   1428 ** Function         bta_hh_gatt_open
   1429 **
   1430 ** Description      process GATT open event.
   1431 **
   1432 ** Parameters:
   1433 **
   1434 *******************************************************************************/
   1435 void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
   1436 {
   1437     tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
   1438     UINT8           *p2;
   1439     tHID_STATUS     status = BTA_HH_ERR;
   1440 
   1441     /* if received invalid callback data , ignore it */
   1442     if (p_cb == NULL || p_data == NULL)
   1443         return;
   1444 
   1445     p2 = p_data->remote_bda;
   1446 
   1447     APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
   1448                       ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
   1449                       ((p2[4])<<8)+ p2[5],p_data->status);
   1450 
   1451     if (p_data->status == BTA_GATT_OK)
   1452     {
   1453         p_cb->is_le_device  = TRUE;
   1454         p_cb->in_use    = TRUE;
   1455         p_cb->conn_id   = p_data->conn_id;
   1456         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
   1457 
   1458         bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   1459 
   1460 #if BTA_HH_DEBUG == TRUE
   1461         APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
   1462 #endif
   1463 
   1464         bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
   1465 
   1466     }
   1467     else /* open failure */
   1468     {
   1469         bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
   1470     }
   1471 
   1472 }
   1473 
   1474 /*******************************************************************************
   1475 **
   1476 ** Function         bta_hh_le_close
   1477 **
   1478 ** Description      This function process the GATT close event and post it as a
   1479 **                  BTA HH internal event
   1480 **
   1481 ** Parameters:
   1482 **
   1483 *******************************************************************************/
   1484 void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
   1485 {
   1486     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
   1487     tBTA_HH_LE_CLOSE    *p_buf = NULL;
   1488     UINT16  sm_event = BTA_HH_GATT_CLOSE_EVT;
   1489 
   1490     if (p_dev_cb != NULL &&
   1491         (p_buf = (tBTA_HH_LE_CLOSE *)GKI_getbuf(sizeof(tBTA_HH_LE_CLOSE))) != NULL)
   1492     {
   1493         p_buf->hdr.event            = sm_event;
   1494         p_buf->hdr.layer_specific   = (UINT16)p_dev_cb->hid_handle;
   1495         p_buf->conn_id              = p_data->conn_id;
   1496         p_buf->reason               = p_data->reason;
   1497 
   1498         p_dev_cb->conn_id           = BTA_GATT_INVALID_CONN_ID;
   1499         p_dev_cb->security_pending  = FALSE;
   1500         bta_sys_sendmsg(p_buf);
   1501     }
   1502 }
   1503 
   1504 /*******************************************************************************
   1505 **
   1506 ** Function         bta_hh_le_search_result
   1507 **
   1508 ** Description      This function process the GATT service search result.
   1509 **
   1510 ** Parameters:
   1511 **
   1512 *******************************************************************************/
   1513 void bta_hh_le_search_result(tBTA_GATTC_SRVC_RES *p_srvc_result)
   1514 {
   1515     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_srvc_result->conn_id);
   1516 
   1517     if (p_dev_cb != NULL)
   1518     {
   1519         switch (p_srvc_result->service_uuid.id.uuid.uu.uuid16)
   1520         {
   1521         case UUID_SERVCLASS_LE_HID:
   1522             if (p_srvc_result->service_uuid.is_primary)
   1523             {
   1524                 /* found HID primamry service */
   1525                 /* TODO: proceed to find battery and device info */
   1526                 if (bta_hh_le_add_hid_srvc_entry(p_dev_cb, p_dev_cb->total_srvc))
   1527                     p_dev_cb->total_srvc ++;
   1528                 APPL_TRACE_DEBUG("num of hid service: %d", p_dev_cb->total_srvc);
   1529             }
   1530             break;
   1531 
   1532         case UUID_SERVCLASS_SCAN_PARAM : /* scan parameter service */
   1533             bta_hh_le_search_scps_chars(p_dev_cb);
   1534             break;
   1535         }
   1536 
   1537     }
   1538 
   1539 }
   1540 
   1541 
   1542 /*******************************************************************************
   1543 **
   1544 ** Function         bta_hh_le_gatt_disc_cmpl
   1545 **
   1546 ** Description      Check to see if the remote device is a LE only device
   1547 **
   1548 ** Parameters:
   1549 **
   1550 *******************************************************************************/
   1551 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
   1552 {
   1553     APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
   1554 
   1555     /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
   1556     if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
   1557     {
   1558         /* assign a special APP ID temp, since device type unknown */
   1559         p_cb->app_id = BTA_HH_APP_ID_LE;
   1560 
   1561         /* set report notification configuration */
   1562         p_cb->clt_cfg_idx = 0;
   1563         bta_hh_le_write_rpt_clt_cfg(p_cb, BTA_HH_LE_SRVC_DEF);
   1564     }
   1565     else /* error, close the GATT connection */
   1566     {
   1567         /* close GATT connection if it's on */
   1568         bta_hh_le_api_disc_act(p_cb);
   1569     }
   1570 }
   1571 
   1572 /*******************************************************************************
   1573 **
   1574 ** Function         bta_hh_le_srvc_expl_srvc
   1575 **
   1576 ** Description      This function discover the next avaible HID service.
   1577 **
   1578 ** Parameters:
   1579 **
   1580 *******************************************************************************/
   1581 void bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB *p_dev_cb)
   1582 {
   1583 #if BTA_HH_DEBUG == TRUE
   1584     APPL_TRACE_DEBUG("bta_hh_le_srvc_expl_srvc cur_srvc_index = %d in_use = %d",
   1585                     p_dev_cb->cur_srvc_index,
   1586                     p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use);
   1587 #endif
   1588 
   1589     if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX &&
   1590         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use)
   1591     {
   1592         if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc)
   1593             /* explore included service first */
   1594             bta_hh_le_search_hid_included(p_dev_cb);
   1595         else
   1596         {
   1597             /* explore characterisc */
   1598             p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
   1599             bta_hh_le_search_hid_chars(p_dev_cb);
   1600         }
   1601     }
   1602     else /* all service discvery finished */
   1603     {
   1604         bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
   1605     }
   1606 }
   1607 
   1608 /*******************************************************************************
   1609 **
   1610 ** Function         bta_hh_le_srvc_search_cmpl
   1611 **
   1612 ** Description      This function process the GATT service search complete.
   1613 **
   1614 ** Parameters:
   1615 **
   1616 *******************************************************************************/
   1617 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
   1618 {
   1619     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   1620 
   1621     /* service search exception or no HID service is supported on remote */
   1622     if (p_dev_cb == NULL)
   1623         return;
   1624 
   1625     if(p_data->status != BTA_GATT_OK || p_dev_cb->total_srvc == 0)
   1626     {
   1627         p_dev_cb->status = BTA_HH_ERR_SDP;
   1628         /* close the connection and report service discovery complete with error */
   1629         bta_hh_le_api_disc_act(p_dev_cb);
   1630     }
   1631     /* GATT service discovery sucessfully finished */
   1632     else
   1633     {
   1634         if (p_dev_cb->disc_active  & BTA_HH_LE_DISC_SCPS)
   1635         {
   1636             p_dev_cb->disc_active  &= ~BTA_HH_LE_DISC_SCPS;
   1637             bta_hh_le_open_cmpl(p_dev_cb);
   1638         }
   1639         else /* discover HID service */
   1640         {
   1641         p_dev_cb->cur_srvc_index = 0;
   1642         bta_hh_le_srvc_expl_srvc(p_dev_cb);
   1643     }
   1644 }
   1645 }
   1646 
   1647 /*******************************************************************************
   1648 **
   1649 ** Function         bta_hh_le_search_hid_included
   1650 **
   1651 ** Description      This function search the included service within the HID service.
   1652 **
   1653 ** Parameters:
   1654 **
   1655 *******************************************************************************/
   1656 static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb)
   1657 {
   1658     tBT_UUID    srvc_cond, char_cond;
   1659     tBTA_GATTC_INCL_SVC_ID  inc_srvc_result;
   1660     tBTA_GATT_SRVC_ID srvc_id;
   1661     tBTA_GATTC_CHAR_ID  char_result;
   1662     tBTA_GATT_CHAR_PROP prop = 0;
   1663 
   1664     bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
   1665 
   1666     srvc_cond.len = LEN_UUID_16;
   1667     srvc_cond.uu.uuid16 = UUID_SERVCLASS_BATTERY;
   1668 
   1669     if (BTA_GATTC_GetFirstIncludedService(p_dev_cb->conn_id,
   1670                             &srvc_id,
   1671                             &srvc_cond,
   1672                             &inc_srvc_result) == BTA_GATT_OK)
   1673     {
   1674         /* read include service UUID */
   1675         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id;
   1676 
   1677         char_cond.len = LEN_UUID_16;
   1678         char_cond.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
   1679 
   1680         /* find the battery characteristic */
   1681         if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
   1682                                     &inc_srvc_result.incl_svc_id,
   1683                                     &char_cond,
   1684                                     &char_result,
   1685                                     &prop) == BTA_GATT_OK)
   1686         {
   1687 
   1688             if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
   1689                                                   char_result.srvc_id.id.inst_id,
   1690                                                   GATT_UUID_BATTERY_LEVEL,
   1691                                                   char_result.char_id.inst_id,
   1692                                                   prop) == NULL)
   1693             {
   1694                 APPL_TRACE_ERROR("Add battery report entry failed !!!")
   1695             }
   1696 
   1697             /* read the battery characteristic */
   1698             BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
   1699                                          &char_result,
   1700                                          BTA_GATT_AUTH_REQ_NONE);
   1701 
   1702             return;
   1703 
   1704         }
   1705         else
   1706         {
   1707             APPL_TRACE_ERROR("Remote device does not have battery level");
   1708         }
   1709     }
   1710 
   1711     p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
   1712 
   1713     bta_hh_le_srvc_expl_srvc(p_dev_cb);
   1714 
   1715 }
   1716 
   1717 /*******************************************************************************
   1718 **
   1719 ** Function         bta_hh_read_battery_level_cmpl
   1720 **
   1721 ** Description      This function process the battery level read
   1722 **
   1723 ** Parameters:
   1724 **
   1725 *******************************************************************************/
   1726 void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1727 {
   1728     UNUSED(status);
   1729     UNUSED(p_data);
   1730 
   1731     p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
   1732     bta_hh_le_srvc_expl_srvc(p_dev_cb);
   1733 }
   1734 /*******************************************************************************
   1735 **
   1736 ** Function         bta_hh_le_search_hid_chars
   1737 **
   1738 ** Description      This function discover all characteristics a service and
   1739 **                  all descriptors available.
   1740 **
   1741 ** Parameters:
   1742 **
   1743 *******************************************************************************/
   1744 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb)
   1745 {
   1746     tBT_UUID    char_cond;
   1747     tBTA_GATTC_CHAR_ID  char_result;
   1748     tBTA_GATT_CHAR_PROP prop;
   1749     BOOLEAN     next = TRUE;
   1750     UINT16      char_uuid = 0;
   1751     tBTA_GATT_SRVC_ID srvc_id;
   1752 
   1753     if (p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx == BTA_HH_LE_DISC_CHAR_NUM ||
   1754         (p_dev_cb->status != BTA_HH_OK && p_dev_cb->status != BTA_HH_ERR_PROTO))
   1755     {
   1756         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
   1757         /* explore next service */
   1758         p_dev_cb->cur_srvc_index ++;
   1759         bta_hh_le_srvc_expl_srvc(p_dev_cb);
   1760         return;
   1761     }
   1762 
   1763     p_dev_cb->hid_srvc[ p_dev_cb->cur_srvc_index].cur_expl_char_idx ++;
   1764     char_uuid = bta_hh_le_disc_char_uuid[p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx - 1];
   1765 
   1766     char_cond.len = LEN_UUID_16;
   1767     char_cond.uu.uuid16 = char_uuid;
   1768 
   1769     bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
   1770 
   1771 #if BTA_HH_DEBUG == TRUE
   1772     APPL_TRACE_DEBUG("bta_hh_le_search_hid_chars: looking for %s(0x%04x)",
   1773                        bta_hh_uuid_to_str(char_uuid), char_uuid);
   1774 #endif
   1775 
   1776     if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
   1777                             &srvc_id,
   1778                             &char_cond,
   1779                             &char_result,
   1780                             &prop) == BTA_GATT_OK)
   1781     {
   1782         switch (char_uuid)
   1783         {
   1784         case GATT_UUID_HID_CONTROL_POINT:
   1785             p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_CP_BIT;
   1786             next = TRUE;
   1787             break;
   1788         case GATT_UUID_HID_INFORMATION:
   1789         case GATT_UUID_HID_REPORT_MAP:
   1790             /* read the char value */
   1791             BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
   1792                                         &char_result,
   1793                                         BTA_GATT_AUTH_REQ_NONE);
   1794             next = FALSE;
   1795             break;
   1796 
   1797         case GATT_UUID_HID_PROTO_MODE:
   1798             p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_PROTO_MODE_BIT;
   1799             next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
   1800             break;
   1801 
   1802         case GATT_UUID_HID_REPORT:
   1803             bta_hh_le_expl_rpt(p_dev_cb, &char_result, &char_cond, prop);
   1804             next = FALSE;
   1805             break;
   1806 
   1807         /* found boot mode report types */
   1808         case GATT_UUID_HID_BT_KB_OUTPUT:
   1809         case GATT_UUID_HID_BT_MOUSE_INPUT:
   1810         case GATT_UUID_HID_BT_KB_INPUT:
   1811             bta_hh_le_expl_boot_rpt(p_dev_cb, char_uuid, prop);
   1812             break;
   1813         }
   1814     }
   1815     else
   1816     {
   1817         if (char_uuid == GATT_UUID_HID_PROTO_MODE)
   1818             next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
   1819 
   1820     }
   1821 
   1822     if (next == TRUE)
   1823     {
   1824         bta_hh_le_search_hid_chars(p_dev_cb);
   1825     }
   1826 }
   1827 
   1828 /*******************************************************************************
   1829 **
   1830 ** Function         bta_hh_le_save_rpt_map
   1831 **
   1832 ** Description      save the report map into the control block.
   1833 **
   1834 ** Parameters:
   1835 **
   1836 *******************************************************************************/
   1837 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1838 {
   1839     UINT8           *pp ;
   1840     tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id];
   1841 
   1842     pp = p_data->p_value->unformat.p_value;
   1843 
   1844     /* save report descriptor */
   1845     if (p_srvc->rpt_map != NULL)
   1846         GKI_freebuf((void*)p_srvc->rpt_map);
   1847 
   1848     if (p_data->p_value->unformat.len > 0)
   1849         p_srvc->rpt_map = (UINT8 *)GKI_getbuf(p_data->p_value->unformat.len);
   1850 
   1851     if (p_srvc->rpt_map != NULL)
   1852     {
   1853         STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->unformat.len);
   1854         p_srvc->descriptor.dl_len = p_data->p_value->unformat.len;
   1855         p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id].rpt_map;
   1856     }
   1857 
   1858     if (bta_hh_le_read_char_dscrpt(p_dev_cb,
   1859                                    UUID_SERVCLASS_LE_HID,
   1860                                p_data->srvc_id.id.inst_id,
   1861                                GATT_UUID_HID_REPORT_MAP,
   1862                                p_data->char_id.inst_id,
   1863                                GATT_UUID_EXT_RPT_REF_DESCR) != BTA_HH_OK)
   1864     {
   1865         bta_hh_le_search_hid_chars(p_dev_cb);
   1866     }
   1867 }
   1868 
   1869 /*******************************************************************************
   1870 **
   1871 ** Function         bta_hh_le_proc_get_rpt_cmpl
   1872 **
   1873 ** Description      Process the Read report complete, send GET_REPORT_EVT to application
   1874 **                  with the report data.
   1875 **
   1876 ** Parameters:
   1877 **
   1878 *******************************************************************************/
   1879 void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1880 {
   1881     BT_HDR              *p_buf = NULL;
   1882     tBTA_HH_LE_RPT      *p_rpt;
   1883     tBTA_HH_HSDATA      hs_data;
   1884     UINT8               *pp ;
   1885 
   1886     if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
   1887     {
   1888         APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
   1889         return;
   1890     }
   1891 
   1892     hs_data.status  = BTA_HH_ERR;
   1893     hs_data.handle  = p_dev_cb->hid_handle;
   1894 
   1895     if (p_data->status == BTA_GATT_OK)
   1896     {
   1897         p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   1898                                             p_data->srvc_id.id.inst_id,//BTA_HH_LE_SRVC_DEF,
   1899                                             p_data->char_id.uuid.uu.uuid16,
   1900                                             p_data->char_id.inst_id);
   1901 
   1902         if (p_rpt != NULL &&
   1903             p_data->p_value != NULL &&
   1904             (p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) +p_data->p_value->unformat.len + 1))) != NULL)
   1905         {
   1906             /* pack data send to app */
   1907             hs_data.status  = BTA_HH_OK;
   1908             p_buf->len = p_data->p_value->unformat.len + 1;
   1909             p_buf->layer_specific = 0;
   1910             p_buf->offset = 0;
   1911 
   1912             /* attach report ID as the first byte of the report before sending it to USB HID driver */
   1913             pp = (UINT8*)(p_buf + 1);
   1914             UINT8_TO_STREAM(pp, p_rpt->rpt_id);
   1915             memcpy(pp, p_data->p_value->unformat.p_value, p_data->p_value->unformat.len);
   1916 
   1917             hs_data.rsp_data.p_rpt_data =p_buf;
   1918         }
   1919     }
   1920 
   1921     p_dev_cb->w4_evt = 0;
   1922     (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
   1923 
   1924     utl_freebuf((void **)&p_buf);
   1925 }
   1926 
   1927 /*******************************************************************************
   1928 **
   1929 ** Function         bta_hh_le_proc_read_proto_mode
   1930 **
   1931 ** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
   1932 **                  with the protocol mode.
   1933 **
   1934 *******************************************************************************/
   1935 void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
   1936 {
   1937     tBTA_HH_HSDATA      hs_data;
   1938 
   1939     hs_data.status  = BTA_HH_ERR;
   1940     hs_data.handle  = p_dev_cb->hid_handle;
   1941     hs_data.rsp_data.proto_mode = p_dev_cb->mode;
   1942 
   1943     if (p_data->status == BTA_GATT_OK && p_data->p_value)
   1944     {
   1945         hs_data.status  = BTA_HH_OK;
   1946         /* match up BTE/BTA report/boot mode def*/
   1947         hs_data.rsp_data.proto_mode = *(p_data->p_value->unformat.p_value);
   1948         /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
   1949         if (hs_data.rsp_data.proto_mode == 0)
   1950             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
   1951         else
   1952             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
   1953 
   1954         p_dev_cb->mode = hs_data.rsp_data.proto_mode;
   1955     }
   1956 #if BTA_HH_DEBUG
   1957     APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
   1958                         (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
   1959 #endif
   1960 
   1961     p_dev_cb->w4_evt = 0;
   1962     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
   1963 
   1964 }
   1965 
   1966 /*******************************************************************************
   1967 **
   1968 ** Function         bta_hh_w4_le_read_char_cmpl
   1969 **
   1970 ** Description      process the GATT read complete in W4_CONN state.
   1971 **
   1972 ** Parameters:
   1973 **
   1974 *******************************************************************************/
   1975 void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   1976 {
   1977     tBTA_GATTC_READ     * p_data = (tBTA_GATTC_READ *)p_buf;
   1978     UINT8               *pp ;
   1979 
   1980     if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL)
   1981     {
   1982         bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
   1983     }
   1984     else
   1985     {
   1986         if (p_data->status == BTA_GATT_OK && p_data->p_value)
   1987         {
   1988             pp = p_data->p_value->unformat.p_value;
   1989 
   1990             switch (p_data->char_id.uuid.uu.uuid16)
   1991             {
   1992            /* save device information */
   1993             case GATT_UUID_HID_INFORMATION:
   1994                 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
   1995                 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
   1996                 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
   1997                 break;
   1998 
   1999             case GATT_UUID_HID_REPORT_MAP:
   2000                 bta_hh_le_save_rpt_map(p_dev_cb, p_data);
   2001                 return;
   2002 
   2003             default:
   2004 #if BTA_HH_DEBUG == TRUE
   2005                 APPL_TRACE_ERROR("Unexpected read %s(0x%04x)",
   2006                                 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
   2007                                 p_data->char_id.uuid.uu.uuid16);
   2008 #endif
   2009                 break;
   2010             }
   2011         }
   2012         else
   2013         {
   2014 #if BTA_HH_DEBUG == TRUE
   2015             APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d",
   2016                                 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
   2017                                 p_data->char_id.uuid.uu.uuid16,
   2018                                 p_data->status);
   2019 #else
   2020             APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", p_data->char_id.uuid.uu.uuid16, p_data->status);
   2021 #endif
   2022         }
   2023         bta_hh_le_search_hid_chars(p_dev_cb);
   2024     }
   2025 
   2026 }
   2027 
   2028 /*******************************************************************************
   2029 **
   2030 ** Function         bta_hh_le_read_char_cmpl
   2031 **
   2032 ** Description      a characteristic value is received.
   2033 **
   2034 ** Parameters:
   2035 **
   2036 *******************************************************************************/
   2037 void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2038 {
   2039     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   2040 
   2041     switch (p_data->char_id.uuid.uu.uuid16)
   2042     {
   2043     /* GET_REPORT */
   2044     case GATT_UUID_HID_REPORT:
   2045     case GATT_UUID_HID_BT_KB_INPUT:
   2046     case GATT_UUID_HID_BT_KB_OUTPUT:
   2047     case GATT_UUID_HID_BT_MOUSE_INPUT:
   2048     case GATT_UUID_BATTERY_LEVEL: /* read battery level */
   2049         bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
   2050         break;
   2051 
   2052     case GATT_UUID_HID_PROTO_MODE:
   2053         bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
   2054         break;
   2055 
   2056     default:
   2057         APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", p_data->char_id.uuid.uu.uuid16);
   2058         break;
   2059     }
   2060 
   2061 }
   2062 
   2063 /*******************************************************************************
   2064 **
   2065 ** Function         bta_hh_le_read_descr_cmpl
   2066 **
   2067 ** Description      read characteristic descriptor is completed in CONN st.
   2068 **
   2069 ** Parameters:
   2070 **
   2071 *******************************************************************************/
   2072 void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2073 {
   2074     tBTA_HH_LE_RPT  *p_rpt;
   2075     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   2076     UINT8   *pp;
   2077 
   2078     /* if a report client configuration */
   2079     if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
   2080     {
   2081         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   2082                                                  BTA_HH_LE_SRVC_DEF,
   2083                                                  p_data->char_id.uuid.uu.uuid16,
   2084                                                  p_data->char_id.inst_id)) != NULL)
   2085         {
   2086             pp = p_data->p_value->unformat.p_value;
   2087             STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
   2088 
   2089             APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
   2090         }
   2091     }
   2092 }
   2093 
   2094 /*******************************************************************************
   2095 **
   2096 ** Function         bta_hh_le_read_battery_level_descr_cmpl
   2097 **
   2098 ** Description      Process report reference descriptor for battery level is completed
   2099 **
   2100 ** Parameters:
   2101 **
   2102 *******************************************************************************/
   2103 void bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ * p_data)
   2104 {
   2105     tBTA_HH_LE_RPT  *p_rpt;
   2106     UINT16 descr_uuid = p_data->descr_type.uuid.uu.uuid16;
   2107 
   2108     /* read report reference descriptor for battery level is completed */
   2109     if (descr_uuid == GATT_UUID_RPT_REF_DESCR)
   2110     {
   2111         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   2112                                             p_data->srvc_id.id.inst_id,
   2113                                             GATT_UUID_BATTERY_LEVEL,
   2114                                             p_data->char_id.inst_id)) == NULL)
   2115         {
   2116             bta_hh_le_search_hid_chars(p_dev_cb);
   2117         }
   2118         else
   2119             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
   2120     }
   2121 }
   2122 
   2123 /*******************************************************************************
   2124 **
   2125 ** Function         bta_hh_w4_le_read_descr_cmpl
   2126 **
   2127 ** Description      read characteristic descriptor is completed in W4_CONN st.
   2128 **
   2129 ** Parameters:
   2130 **
   2131 *******************************************************************************/
   2132 void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2133 {
   2134     tBTA_HH_LE_RPT  *p_rpt;
   2135     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
   2136     UINT16 char_uuid16;
   2137 
   2138     if (p_data == NULL)
   2139         return;
   2140 
   2141     char_uuid16 = p_data->char_id.uuid.uu.uuid16;
   2142 
   2143 #if BTA_HH_DEBUG == TRUE
   2144     APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
   2145                         bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
   2146                         p_data->descr_type.uuid.uu.uuid16);
   2147 #endif
   2148     switch (char_uuid16)
   2149     {
   2150     case GATT_UUID_HID_REPORT:
   2151         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   2152                                             p_data->srvc_id.id.inst_id,
   2153                                             GATT_UUID_HID_REPORT,
   2154                                             p_data->char_id.inst_id)) == NULL)
   2155         {
   2156             bta_hh_le_search_hid_chars(p_dev_cb);
   2157         }
   2158         else
   2159             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
   2160         break;
   2161 
   2162     case GATT_UUID_HID_REPORT_MAP:
   2163         bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
   2164         break;
   2165 
   2166     case GATT_UUID_BATTERY_LEVEL:
   2167         bta_hh_le_read_battery_level_descr_cmpl(p_dev_cb, p_data);
   2168         break;
   2169 
   2170     default:
   2171         APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
   2172         break;
   2173     }
   2174 }
   2175 
   2176 /*******************************************************************************
   2177 **
   2178 ** Function         bta_hh_w4_le_write_cmpl
   2179 **
   2180 ** Description      Write charactersitic complete event at W4_CONN st.
   2181 **
   2182 ** Parameters:
   2183 **
   2184 *******************************************************************************/
   2185 void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2186 {
   2187     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   2188 
   2189     if (p_data == NULL)
   2190         return;
   2191 
   2192     if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
   2193     {
   2194         p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
   2195 
   2196         if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) != 0)
   2197         {
   2198             bta_hh_le_search_hid_chars(p_dev_cb);
   2199         }
   2200         else
   2201         {
   2202             bta_hh_le_open_cmpl(p_dev_cb);
   2203         }
   2204     }
   2205 }
   2206 
   2207 /*******************************************************************************
   2208 **
   2209 ** Function         bta_hh_le_write_cmpl
   2210 **
   2211 ** Description      Write charactersitic complete event at CONN st.
   2212 **
   2213 ** Parameters:
   2214 **
   2215 *******************************************************************************/
   2216 void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2217 {
   2218     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   2219     tBTA_HH_CBDATA      cback_data ;
   2220     UINT16              cb_evt = p_dev_cb->w4_evt;
   2221 
   2222     if (p_data == NULL  || cb_evt == 0)
   2223         return;
   2224 
   2225 #if BTA_HH_DEBUG
   2226     APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
   2227 #endif
   2228     switch (p_data->char_id.uuid.uu.uuid16)
   2229     {
   2230     /* Set protocol finished */
   2231     case GATT_UUID_HID_PROTO_MODE:
   2232         cback_data.handle  = p_dev_cb->hid_handle;
   2233         if (p_data->status == BTA_GATT_OK)
   2234         {
   2235             bta_hh_le_register_input_notif(p_dev_cb, p_data->srvc_id.id.inst_id, p_dev_cb->mode, FALSE);
   2236             cback_data.status = BTA_HH_OK;
   2237         }
   2238         else
   2239             cback_data.status =  BTA_HH_ERR;
   2240         p_dev_cb->w4_evt = 0;
   2241         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   2242         break;
   2243 
   2244     /* Set Report finished */
   2245     case GATT_UUID_HID_REPORT:
   2246     case GATT_UUID_HID_BT_KB_INPUT:
   2247     case GATT_UUID_HID_BT_MOUSE_INPUT:
   2248     case GATT_UUID_HID_BT_KB_OUTPUT:
   2249         cback_data.handle  = p_dev_cb->hid_handle;
   2250         cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
   2251         p_dev_cb->w4_evt = 0;
   2252         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   2253         break;
   2254 
   2255     case GATT_UUID_SCAN_INT_WINDOW:
   2256         bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
   2257         break;
   2258 
   2259 
   2260     default:
   2261         break;
   2262     }
   2263 
   2264 }
   2265 
   2266 /*******************************************************************************
   2267 **
   2268 ** Function         bta_hh_le_write_char_descr_cmpl
   2269 **
   2270 ** Description      Write charactersitic descriptor complete event
   2271 **
   2272 ** Parameters:
   2273 **
   2274 *******************************************************************************/
   2275 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2276 {
   2277     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
   2278     UINT8   srvc_inst_id, hid_inst_id;
   2279 
   2280     /* only write client configuration possible */
   2281     if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
   2282     {
   2283         srvc_inst_id = p_data->srvc_id.id.inst_id;
   2284         hid_inst_id = srvc_inst_id;
   2285         switch (p_data->char_id.uuid.uu.uuid16)
   2286         {
   2287         case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
   2288             hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
   2289             /* fall through */
   2290         case GATT_UUID_HID_BT_KB_INPUT:
   2291         case GATT_UUID_HID_BT_MOUSE_INPUT:
   2292         case GATT_UUID_HID_REPORT:
   2293             if (p_data->status == BTA_GATT_OK)
   2294                 p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value =
   2295                         BTA_GATT_CLT_CONFIG_NOTIFICATION;
   2296             p_dev_cb->clt_cfg_idx ++;
   2297             bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
   2298 
   2299             break;
   2300 
   2301         case GATT_UUID_SCAN_REFRESH:
   2302             bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
   2303             break;
   2304 
   2305         default:
   2306             APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16);
   2307         }
   2308     }
   2309     else
   2310     {
   2311 #if BTA_HH_DEBUG == TRUE
   2312         APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)",
   2313                         bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
   2314                         p_data->descr_type.uuid.uu.uuid16);
   2315 #else
   2316         APPL_TRACE_ERROR("Unexpected write to (0x%04x)", p_data->descr_type.uuid.uu.uuid16);
   2317 #endif
   2318     }
   2319 
   2320 }
   2321 
   2322 /*******************************************************************************
   2323 **
   2324 ** Function         bta_hh_le_input_rpt_notify
   2325 **
   2326 ** Description      process the notificaton event, most likely for input report.
   2327 **
   2328 ** Parameters:
   2329 **
   2330 *******************************************************************************/
   2331 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
   2332 {
   2333     tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
   2334     UINT8           app_id;
   2335     UINT8           *p_buf;
   2336     tBTA_HH_LE_RPT  *p_rpt;
   2337 
   2338     if (p_dev_cb == NULL)
   2339     {
   2340         APPL_TRACE_ERROR("notification received from Unknown device");
   2341         return;
   2342     }
   2343     app_id= p_dev_cb->app_id;
   2344 
   2345     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
   2346                                         BTA_HH_LE_SRVC_DEF,
   2347                                         p_data->char_id.char_id.uuid.uu.uuid16,
   2348                                         p_data->char_id.char_id.inst_id);
   2349     if (p_rpt == NULL)
   2350     {
   2351         APPL_TRACE_ERROR("notification received for Unknown Report");
   2352         return;
   2353     }
   2354 
   2355     if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
   2356         app_id = BTA_HH_APP_ID_MI;
   2357     else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
   2358         app_id = BTA_HH_APP_ID_KB;
   2359 
   2360     APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
   2361 
   2362     /* need to append report ID to the head of data */
   2363     if (p_rpt->rpt_id != 0)
   2364     {
   2365         if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(p_data->len + 1))) == NULL)
   2366         {
   2367             APPL_TRACE_ERROR("No resources to send report data");
   2368             return;
   2369         }
   2370 
   2371         p_buf[0] = p_rpt->rpt_id;
   2372         memcpy(&p_buf[1], p_data->value, p_data->len);
   2373         ++p_data->len;
   2374     } else {
   2375         p_buf = p_data->value;
   2376     }
   2377 
   2378     bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
   2379                     p_buf,
   2380                     p_data->len,
   2381                     p_dev_cb->mode,
   2382                     0 , /* no sub class*/
   2383                     p_dev_cb->dscp_info.ctry_code,
   2384                     p_dev_cb->addr,
   2385                     app_id);
   2386 
   2387     if (p_buf != p_data->value)
   2388         GKI_freebuf(p_buf);
   2389 }
   2390 
   2391 /*******************************************************************************
   2392 **
   2393 ** Function         bta_hh_gatt_open_fail
   2394 **
   2395 ** Description      action function to process the open fail
   2396 **
   2397 ** Returns          void
   2398 **
   2399 *******************************************************************************/
   2400 void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2401 {
   2402     tBTA_HH_CONN            conn_dat ;
   2403     tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc[0];
   2404 
   2405     /* open failure in the middle of service discovery, clear all services */
   2406     if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS)
   2407     {
   2408         bta_hh_clear_service_cache(p_cb);
   2409     }
   2410 
   2411     p_cb->disc_active = BTA_HH_LE_DISC_NONE;
   2412     /* Failure in opening connection or GATT discovery failure */
   2413     conn_dat.handle = p_cb->hid_handle;
   2414     memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
   2415     conn_dat.le_hid = TRUE;
   2416     conn_dat.scps_supported = p_cb->scps_supported;
   2417 
   2418     if (p_cb->status == BTA_HH_OK)
   2419         conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
   2420     else
   2421         conn_dat.status = p_cb->status;
   2422 
   2423     /* Report OPEN fail event */
   2424     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
   2425 
   2426 }
   2427 
   2428 /*******************************************************************************
   2429 **
   2430 ** Function         bta_hh_gatt_close
   2431 **
   2432 ** Description      action function to process the GATT close int he state machine.
   2433 **
   2434 ** Returns          void
   2435 **
   2436 *******************************************************************************/
   2437 void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2438 {
   2439     tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
   2440 
   2441     /* finaliza device driver */
   2442     bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
   2443     /* update total conn number */
   2444     bta_hh_cb.cnt_num --;
   2445 
   2446     disc_dat.handle = p_cb->hid_handle;
   2447     disc_dat.status = p_cb->status;
   2448 
   2449     (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
   2450 
   2451     /* if no connection is active and HH disable is signaled, disable service */
   2452     if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
   2453     {
   2454         bta_hh_disc_cmpl();
   2455     }
   2456     else
   2457     {
   2458 #if (BTA_HH_LE_RECONN == TRUE)
   2459     if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
   2460     {
   2461         bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
   2462     }
   2463 #endif
   2464     }
   2465 
   2466     return;
   2467 
   2468 }
   2469 
   2470 /*******************************************************************************
   2471 **
   2472 ** Function         bta_hh_le_api_disc_act
   2473 **
   2474 ** Description      initaite a Close API to a remote HID device
   2475 **
   2476 ** Returns          void
   2477 **
   2478 *******************************************************************************/
   2479 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
   2480 {
   2481     if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
   2482     {
   2483         BTA_GATTC_Close(p_cb->conn_id);
   2484         /* remove device from background connection if intended to disconnect,
   2485            do not allow reconnection */
   2486         bta_hh_le_remove_dev_bg_conn(p_cb);
   2487     }
   2488 }
   2489 
   2490 /*******************************************************************************
   2491 **
   2492 ** Function         bta_hh_le_get_rpt
   2493 **
   2494 ** Description      GET_REPORT on a LE HID Report
   2495 **
   2496 ** Returns          void
   2497 **
   2498 *******************************************************************************/
   2499 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
   2500 {
   2501     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);
   2502     tBTA_GATTC_CHAR_ID  char_id;
   2503     UINT16  srvc_uuid = UUID_SERVCLASS_LE_HID;
   2504 
   2505     if (p_rpt == NULL)
   2506     {
   2507         APPL_TRACE_ERROR("bta_hh_le_get_rpt: no matching report");
   2508         return;
   2509     }
   2510     if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
   2511         srvc_uuid = UUID_SERVCLASS_BATTERY;
   2512 
   2513     p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
   2514 
   2515     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, srvc_uuid, &char_id.srvc_id);
   2516     bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
   2517 
   2518     BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
   2519                                  &char_id,
   2520                                  BTA_GATT_AUTH_REQ_NONE);
   2521 }
   2522 
   2523 /*******************************************************************************
   2524 **
   2525 ** Function         bta_hh_le_write_rpt
   2526 **
   2527 ** Description      SET_REPORT/or DATA output on a LE HID Report
   2528 **
   2529 ** Returns          void
   2530 **
   2531 *******************************************************************************/
   2532 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst,
   2533                          tBTA_GATTC_WRITE_TYPE   write_type,
   2534                          tBTA_HH_RPT_TYPE r_type,
   2535                          BT_HDR *p_buf, UINT16 w4_evt )
   2536 {
   2537     tBTA_HH_LE_RPT  *p_rpt;
   2538     tBTA_GATTC_CHAR_ID  char_id;
   2539     UINT8   *p_value, rpt_id;
   2540 
   2541     if (p_buf == NULL || p_buf->len == 0)
   2542     {
   2543         APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data");
   2544         return;
   2545     }
   2546 
   2547     /* strip report ID from the data */
   2548     p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
   2549     STREAM_TO_UINT8(rpt_id, p_value);
   2550     p_buf->len -= 1;
   2551 
   2552     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
   2553 
   2554     if (p_rpt == NULL)
   2555     {
   2556         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
   2557         return;
   2558     }
   2559 
   2560     APPL_TRACE_ERROR("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len);
   2561 
   2562     p_cb->w4_evt = w4_evt;
   2563 
   2564     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
   2565     bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
   2566 
   2567     BTA_GATTC_WriteCharValue(p_cb->conn_id,
   2568                              &char_id,
   2569                              write_type, /* default to use write request */
   2570                              p_buf->len,
   2571                              p_value,
   2572                              BTA_GATT_AUTH_REQ_NONE);
   2573 
   2574 }
   2575 
   2576 /*******************************************************************************
   2577 **
   2578 ** Function         bta_hh_le_suspend
   2579 **
   2580 ** Description      send LE suspend or exit suspend mode to remote device.
   2581 **
   2582 ** Returns          void
   2583 **
   2584 *******************************************************************************/
   2585 void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
   2586 {
   2587     UINT8 i;
   2588     tBTA_GATTC_CHAR_ID  char_id;
   2589 
   2590     ctrl_type -= BTA_HH_CTRL_SUSPEND;
   2591 
   2592     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
   2593     {
   2594         bta_hh_le_fill_16bits_srvc_id(TRUE, i, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
   2595         bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_CONTROL_POINT, &char_id.char_id);
   2596 
   2597         BTA_GATTC_WriteCharValue(p_cb->conn_id,
   2598                                  &char_id,
   2599                                  BTA_GATTC_TYPE_WRITE_NO_RSP, /* default to use write request */
   2600                                  1,
   2601                                  &ctrl_type,
   2602                                  BTA_GATT_AUTH_REQ_NONE);
   2603     }
   2604 }
   2605 
   2606 /*******************************************************************************
   2607 **
   2608 ** Function         bta_hh_le_write_dev_act
   2609 **
   2610 ** Description      Write LE device action. can be SET/GET/DATA transaction.
   2611 **
   2612 ** Returns          void
   2613 **
   2614 *******************************************************************************/
   2615 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
   2616 {
   2617     switch(p_data->api_sndcmd.t_type)
   2618     {
   2619         case HID_TRANS_SET_PROTOCOL:
   2620             p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
   2621             bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
   2622             break;
   2623 
   2624         case HID_TRANS_GET_PROTOCOL:
   2625             bta_hh_le_get_protocol_mode(p_cb);
   2626             break;
   2627 
   2628         case HID_TRANS_GET_REPORT:
   2629             bta_hh_le_get_rpt(p_cb,
   2630                               BTA_HH_LE_SRVC_DEF,
   2631                               p_data->api_sndcmd.param,
   2632                               p_data->api_sndcmd.rpt_id);
   2633             break;
   2634 
   2635         case HID_TRANS_SET_REPORT:
   2636             bta_hh_le_write_rpt(p_cb,
   2637                                 BTA_HH_LE_SRVC_DEF,
   2638                                 BTA_GATTC_TYPE_WRITE,
   2639                                 p_data->api_sndcmd.param,
   2640                                 p_data->api_sndcmd.p_data,
   2641                                 BTA_HH_SET_RPT_EVT);
   2642             break;
   2643 
   2644         case HID_TRANS_DATA:  /* output report */
   2645 
   2646             bta_hh_le_write_rpt(p_cb,
   2647                                 BTA_HH_LE_SRVC_DEF,
   2648                                 BTA_GATTC_TYPE_WRITE_NO_RSP,
   2649                                 p_data->api_sndcmd.param,
   2650                                 p_data->api_sndcmd.p_data,
   2651                                 BTA_HH_DATA_EVT);
   2652             break;
   2653 
   2654         case HID_TRANS_CONTROL:
   2655             /* no handshake event will be generated */
   2656             /* if VC_UNPLUG is issued, set flag */
   2657             if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
   2658                 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
   2659             {
   2660                 bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
   2661             }
   2662             break;
   2663 
   2664         default:
   2665             APPL_TRACE_ERROR("unsupported trsanction for LE HID device: %d", p_data->api_sndcmd.t_type);
   2666             break;
   2667     }
   2668 }
   2669 
   2670 /*******************************************************************************
   2671 **
   2672 ** Function         bta_hh_le_get_dscp_act
   2673 **
   2674 ** Description      Send ReportDescriptor to application for all HID services.
   2675 **
   2676 ** Returns          void
   2677 **
   2678 *******************************************************************************/
   2679 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
   2680 {
   2681     UINT8 i;
   2682 
   2683     for (i = 0 ;i < BTA_HH_LE_HID_SRVC_MAX; i ++)
   2684     {
   2685         if (p_cb->hid_srvc[i].in_use)
   2686         {
   2687             p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len;
   2688             p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list;
   2689 
   2690             (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
   2691         }
   2692         else
   2693             break;
   2694     }
   2695 }
   2696 
   2697 /*******************************************************************************
   2698 **
   2699 ** Function         bta_hh_le_add_dev_bg_conn
   2700 **
   2701 ** Description      Remove a LE HID device from back ground connection procedure.
   2702 **
   2703 ** Returns          void
   2704 **
   2705 *******************************************************************************/
   2706 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
   2707 {
   2708     UINT8           sec_flag=0;
   2709     BOOLEAN         to_add = TRUE;
   2710 
   2711     if (check_bond)
   2712     {
   2713         /* start reconnection if remote is a bonded device */
   2714         /* verify bond */
   2715         BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   2716 
   2717         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
   2718             to_add = FALSE;
   2719     }
   2720 
   2721     if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
   2722         !p_cb->in_bg_conn && to_add)
   2723     {
   2724         /* add device into BG connection to accept remote initiated connection */
   2725         BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
   2726         p_cb->in_bg_conn = TRUE;
   2727 
   2728         BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
   2729     }
   2730     return;
   2731 }
   2732 
   2733 /*******************************************************************************
   2734 **
   2735 ** Function         bta_hh_le_add_device
   2736 **
   2737 ** Description      Add a LE HID device as a known device, and also add the address
   2738 **                  into back ground connection WL for incoming connection.
   2739 **
   2740 ** Returns          void
   2741 **
   2742 *******************************************************************************/
   2743 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
   2744 {
   2745     p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
   2746     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
   2747 
   2748     /* update DI information */
   2749     bta_hh_update_di_info(p_cb,
   2750                           p_dev_info->dscp_info.vendor_id,
   2751                           p_dev_info->dscp_info.product_id,
   2752                           p_dev_info->dscp_info.version,
   2753                           p_dev_info->dscp_info.flag);
   2754 
   2755     /* add to BTA device list */
   2756     bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
   2757                               p_dev_info->attr_mask,
   2758                               &p_dev_info->dscp_info.descriptor,
   2759                               p_dev_info->sub_class,
   2760                               p_dev_info->dscp_info.ssr_max_latency,
   2761                               p_dev_info->dscp_info.ssr_min_tout,
   2762                               p_dev_info->app_id);
   2763 
   2764     bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
   2765 
   2766     return p_cb->hid_handle;
   2767 }
   2768 
   2769 /*******************************************************************************
   2770 **
   2771 ** Function         bta_hh_le_remove_dev_bg_conn
   2772 **
   2773 ** Description      Remove a LE HID device from back ground connection procedure.
   2774 **
   2775 ** Returns          void
   2776 **
   2777 *******************************************************************************/
   2778 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
   2779 {
   2780     if (p_dev_cb->in_bg_conn)
   2781     {
   2782         p_dev_cb->in_bg_conn = FALSE;
   2783 
   2784         BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
   2785     }
   2786 }
   2787 
   2788 /*******************************************************************************
   2789 **
   2790 ** Function         bta_hh_le_update_scpp
   2791 **
   2792 ** Description      action function to update the scan parameters on remote HID
   2793 **                  device
   2794 **
   2795 ** Parameters:
   2796 **
   2797 *******************************************************************************/
   2798 void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
   2799 {
   2800     tBTA_GATTC_CHAR_ID  char_id;
   2801     UINT8   value[4], *p = value;
   2802     tBTA_HH_CBDATA      cback_data ;
   2803 
   2804     if (!p_dev_cb->is_le_device ||
   2805         p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
   2806         p_dev_cb->scps_supported == FALSE)
   2807     {
   2808         APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP ");
   2809 
   2810         cback_data.handle = p_dev_cb->hid_handle;
   2811         cback_data.status = BTA_HH_ERR;
   2812         (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
   2813 
   2814         return;
   2815     }
   2816 
   2817     p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
   2818 
   2819     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
   2820     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
   2821 
   2822     bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
   2823     bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_INT_WINDOW, &char_id.char_id);
   2824 
   2825     BTA_GATTC_WriteCharValue(p_dev_cb->conn_id,
   2826                              &char_id,
   2827                              BTA_GATTC_TYPE_WRITE_NO_RSP,
   2828                              2,
   2829                              value,
   2830                              BTA_GATT_AUTH_REQ_NONE);
   2831 
   2832 }
   2833 
   2834 /*******************************************************************************
   2835 **
   2836 ** Function         bta_hh_gattc_callback
   2837 **
   2838 ** Description      This is GATT client callback function used in BTA HH.
   2839 **
   2840 ** Parameters:
   2841 **
   2842 *******************************************************************************/
   2843 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
   2844 {
   2845     tBTA_HH_DEV_CB *p_dev_cb;
   2846     UINT16          evt;
   2847 #if BTA_HH_DEBUG
   2848     APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
   2849 #endif
   2850     if (p_data == NULL)
   2851         return;
   2852 
   2853     switch (event)
   2854     {
   2855         case BTA_GATTC_REG_EVT: /* 0 */
   2856             bta_hh_le_register_cmpl(&p_data->reg_oper);
   2857             break;
   2858 
   2859         case BTA_GATTC_DEREG_EVT: /* 1 */
   2860             bta_hh_cleanup_disable(p_data->reg_oper.status);
   2861             break;
   2862 
   2863         case BTA_GATTC_OPEN_EVT: /* 2 */
   2864             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
   2865             if (p_dev_cb) {
   2866                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
   2867             }
   2868             break;
   2869 
   2870         case BTA_GATTC_READ_CHAR_EVT: /* 3 */
   2871         case BTA_GATTC_READ_DESCR_EVT: /* 8 */
   2872             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
   2873             if (event == BTA_GATTC_READ_CHAR_EVT)
   2874                 evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
   2875             else
   2876                 evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
   2877 
   2878             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
   2879             break;
   2880 
   2881         case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
   2882         case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
   2883             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
   2884             if (event == BTA_GATTC_WRITE_CHAR_EVT)
   2885                 evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
   2886             else
   2887                 evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
   2888 
   2889             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
   2890             break;
   2891 
   2892         case BTA_GATTC_CLOSE_EVT: /* 5 */
   2893             bta_hh_le_close(&p_data->close);
   2894             break;
   2895 
   2896         case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
   2897             bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
   2898             break;
   2899 
   2900         case BTA_GATTC_SEARCH_RES_EVT: /* 7 */
   2901             bta_hh_le_search_result(&p_data->srvc_res);
   2902             break;
   2903 
   2904 
   2905 
   2906         case BTA_GATTC_NOTIF_EVT: /* 10 */
   2907             bta_hh_le_input_rpt_notify(&p_data->notify);
   2908             break;
   2909 
   2910         case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
   2911             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
   2912             if (p_dev_cb) {
   2913                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
   2914                               (tBTA_HH_DATA *)&p_data->enc_cmpl);
   2915             }
   2916             break;
   2917 
   2918         default:
   2919             break;
   2920     }
   2921 }
   2922 
   2923 /*******************************************************************************
   2924 **
   2925 ** Function         bta_hh_le_hid_read_rpt_clt_cfg
   2926 **
   2927 ** Description      a test command to read report descriptor client configuration
   2928 **
   2929 ** Returns          void
   2930 **
   2931 *******************************************************************************/
   2932 void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
   2933 {
   2934     tBTA_HH_DEV_CB *p_cb = NULL;
   2935     tBTA_HH_LE_RPT *p_rpt ;
   2936     UINT8           index = BTA_HH_IDX_INVALID;
   2937 
   2938     index = bta_hh_find_cb(bd_addr);
   2939     if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
   2940     {
   2941         APPL_TRACE_ERROR("unknown device");
   2942         return;
   2943     }
   2944 
   2945     p_cb = &bta_hh_cb.kdev[index];
   2946 
   2947     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);
   2948 
   2949     if (p_rpt == NULL)
   2950     {
   2951         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
   2952         return;
   2953     }
   2954 
   2955     bta_hh_le_read_char_dscrpt(p_cb,
   2956                                UUID_SERVCLASS_LE_HID,
   2957                                BTA_HH_LE_SRVC_DEF,
   2958                                p_rpt->uuid,
   2959                                p_rpt->inst_id,
   2960                                GATT_UUID_CHAR_CLIENT_CONFIG);
   2961 
   2962 
   2963 
   2964     return;
   2965 }
   2966 
   2967 /*******************************************************************************
   2968 **
   2969 ** Function         bta_hh_le_search_scps
   2970 **
   2971 ** Description      discovery scan parameter service if act as report host, otherwise
   2972 **                  finish LE connection.
   2973 **
   2974 ** Parameters:
   2975 **
   2976 *******************************************************************************/
   2977 static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb)
   2978 {
   2979     tBT_UUID        pri_srvc;
   2980 
   2981     if ( p_cb->mode == BTA_HH_PROTO_RPT_MODE)
   2982     {
   2983         p_cb->disc_active  |= BTA_HH_LE_DISC_SCPS;
   2984         /* start  service discovery for Scan Parameter service */
   2985         pri_srvc.len        = LEN_UUID_16;
   2986         pri_srvc.uu.uuid16  = UUID_SERVCLASS_SCAN_PARAM;
   2987 
   2988         BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
   2989     }
   2990     else
   2991         bta_hh_le_open_cmpl(p_cb);
   2992 }
   2993 
   2994 /*******************************************************************************
   2995 **
   2996 ** Function         bta_hh_le_search_scps_chars
   2997 **
   2998 ** Description      find ScPS optional characteristics scan refresh
   2999 **
   3000 ** Parameters:
   3001 **
   3002 *******************************************************************************/
   3003 static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb)
   3004 {
   3005     tBTA_GATT_SRVC_ID   srvc_id;
   3006     tBT_UUID            char_cond;
   3007     tBTA_GATTC_CHAR_ID  char_result;
   3008     tBTA_GATT_CHAR_PROP prop;
   3009 
   3010     p_cb->scps_supported = TRUE;
   3011     bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_SCAN_PARAM, &srvc_id);
   3012 
   3013     char_cond.len   = LEN_UUID_16;
   3014     char_cond.uu.uuid16 = GATT_UUID_SCAN_REFRESH;
   3015 
   3016     /* look for scan refresh */
   3017     if (BTA_GATTC_GetFirstChar( p_cb->conn_id,
   3018                                 &srvc_id,
   3019                                 &char_cond,
   3020                                 &char_result,
   3021                                 &prop) == BTA_GATT_OK)
   3022     {
   3023         if (prop & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
   3024             p_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
   3025         else
   3026             p_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
   3027 
   3028     }
   3029 }
   3030 
   3031 /*******************************************************************************
   3032 **
   3033 ** Function         bta_hh_le_register_scpp_notif
   3034 **
   3035 ** Description      register scan parameter refresh notitication complete
   3036 **
   3037 **
   3038 ** Parameters:
   3039 **
   3040 *******************************************************************************/
   3041 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
   3042 {
   3043     UINT8               sec_flag=0;
   3044     tBTA_GATTC_CHAR_ID  char_id;
   3045 
   3046     /* if write scan parameter sucessful */
   3047     /* if bonded and notification is not enabled, configure the client configuration */
   3048     if (status == BTA_GATT_OK &&
   3049         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
   3050         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
   3051     {
   3052         BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
   3053         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
   3054         {
   3055             if (bta_hh_le_write_char_clt_cfg (p_dev_cb,
   3056                                               BTA_HH_SCPP_INST_DEF,
   3057                                               UUID_SERVCLASS_SCAN_PARAM,
   3058                                               BTA_HH_SCPP_INST_DEF,
   3059                                               GATT_UUID_SCAN_REFRESH,
   3060                                               BTA_GATT_CLT_CONFIG_NOTIFICATION))
   3061             {
   3062                 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
   3063                 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_REFRESH, &char_id.char_id);
   3064 
   3065                 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
   3066                                                    p_dev_cb->addr,
   3067                                                    &char_id);
   3068                 return;
   3069             }
   3070         }
   3071     }
   3072     bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
   3073 }
   3074 
   3075 /*******************************************************************************
   3076 **
   3077 ** Function         bta_hh_le_register_scpp_notif_cmpl
   3078 **
   3079 ** Description      action function to register scan parameter refresh notitication
   3080 **
   3081 ** Parameters:
   3082 **
   3083 *******************************************************************************/
   3084 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
   3085 {
   3086     tBTA_HH_CBDATA      cback_data ;
   3087     UINT16              cb_evt = p_dev_cb->w4_evt;
   3088 
   3089     if (status == BTA_GATT_OK)
   3090         p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
   3091 
   3092     cback_data.handle  = p_dev_cb->hid_handle;
   3093     cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
   3094     p_dev_cb->w4_evt = 0;
   3095     (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
   3096 
   3097 
   3098 }
   3099 
   3100 /*******************************************************************************
   3101 **
   3102 ** Function         bta_hh_process_cache_rpt
   3103 **
   3104 ** Description      Process the cached reports
   3105 **
   3106 ** Parameters:
   3107 **
   3108 *******************************************************************************/
   3109 static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
   3110                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
   3111                                       UINT8 num_rpt)
   3112 {
   3113     UINT8                       i = 0;
   3114     tBTA_HH_LE_RPT              *p_rpt;
   3115 
   3116     if (num_rpt != 0)  /* no cache is found */
   3117     {
   3118         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].in_use = TRUE;
   3119 
   3120         /* set the descriptor info */
   3121         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dl_len =
   3122                 p_cb->dscp_info.descriptor.dl_len;
   3123         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dsc_list =
   3124                     p_cb->dscp_info.descriptor.dsc_list;
   3125 
   3126         for (; i <num_rpt; i ++, p_rpt_cache ++)
   3127         {
   3128             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
   3129                                                BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id),
   3130                                                p_rpt_cache->rpt_uuid,
   3131                                                BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt_cache->inst_id),
   3132                                                p_rpt_cache->prop))  == NULL)
   3133             {
   3134                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
   3135                 break;
   3136             }
   3137             else
   3138             {
   3139                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
   3140                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
   3141 
   3142                 if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
   3143                     p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
   3144                     (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
   3145                 {
   3146                     p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
   3147                 }
   3148             }
   3149         }
   3150     }
   3151 }
   3152 
   3153 #endif
   3154 
   3155 
   3156 
   3157 
   3158