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