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