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