bta_hh_le.cc revision d8f09d077d9017a522c17f4b9a49328b0ed3e91e
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#define LOG_TAG "bt_bta_hh"
20
21#include "bta_api.h"
22#include "bta_hh_int.h"
23
24#if (BTA_HH_LE_INCLUDED == TRUE)
25
26#include <string.h>
27
28#include <list>
29#include <unordered_map>
30#include <unordered_set>
31#include <vector>
32
33#include "bta_api.h"
34#include "bta_gatt_api.h"
35#include "bta_hh_co.h"
36#include "btm_api.h"
37#include "btm_ble_api.h"
38#include "btm_int.h"
39#include "osi/include/log.h"
40#include "srvc_api.h"
41#include "stack/include/l2c_api.h"
42#include "utl.h"
43
44using std::vector;
45
46#ifndef BTA_HH_LE_RECONN
47#define BTA_HH_LE_RECONN    true
48#endif
49
50#define BTA_HH_APP_ID_LE            0xff
51
52#define BTA_HH_LE_RPT_TYPE_VALID(x)     ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
53
54#define BTA_HH_LE_PROTO_BOOT_MODE      0x00
55#define BTA_HH_LE_PROTO_REPORT_MODE      0x01
56
57#define BTA_LE_HID_RTP_UUID_MAX     5
58static const uint16_t bta_hh_uuid_to_rtp_type[BTA_LE_HID_RTP_UUID_MAX][2] =
59{
60    {GATT_UUID_HID_REPORT,       BTA_HH_RPTT_INPUT},
61    {GATT_UUID_HID_BT_KB_INPUT,  BTA_HH_RPTT_INPUT},
62    {GATT_UUID_HID_BT_KB_OUTPUT, BTA_HH_RPTT_OUTPUT},
63    {GATT_UUID_HID_BT_MOUSE_INPUT, BTA_HH_RPTT_INPUT},
64    {GATT_UUID_BATTERY_LEVEL,      BTA_HH_RPTT_INPUT}
65};
66
67
68static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
69static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, bool check_bond);
70//TODO(jpawlowski): uncomment when fixed
71// static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
72//                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
73//                                       uint8_t num_rpt);
74
75#define GATT_READ_CHAR 0
76#define GATT_READ_DESC 1
77#define GATT_WRITE_CHAR 2
78#define GATT_WRITE_DESC 3
79
80/* Holds pending GATT operations */
81struct gatt_operation {
82    uint8_t type;
83    uint16_t handle;
84    GATT_READ_OP_CB read_cb;
85    void* read_cb_data;
86    GATT_WRITE_OP_CB write_cb;
87    void* write_cb_data;
88
89    /* write-specific fields */
90    tBTA_GATTC_WRITE_TYPE write_type;
91    vector<uint8_t> value;
92};
93
94// maps connection id to operations waiting for execution
95static std::unordered_map<uint16_t, std::list<gatt_operation>> gatt_op_queue;
96// contain connection ids that currently execute operations
97static std::unordered_set<uint16_t> gatt_op_queue_executing;
98
99static void mark_as_not_executing(uint16_t conn_id) {
100    gatt_op_queue_executing.erase(conn_id);
101}
102
103static void gatt_op_queue_clean(uint16_t conn_id) {
104    gatt_op_queue.erase(conn_id);
105    gatt_op_queue_executing.erase(conn_id);
106}
107
108static void gatt_execute_next_op(uint16_t conn_id);
109GATT_READ_OP_CB act_read_cb = NULL;
110void* act_read_cb_data = NULL;
111static void gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t *value, void* data) {
112    GATT_READ_OP_CB tmp_cb = act_read_cb;
113    void* tmp_cb_data = act_read_cb_data;
114
115    act_read_cb = NULL;
116    act_read_cb_data = NULL;
117
118    mark_as_not_executing(conn_id);
119    gatt_execute_next_op(conn_id);
120
121    if (tmp_cb) {
122        tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
123        return;
124    }
125}
126
127GATT_WRITE_OP_CB act_write_cb = NULL;
128void* act_write_cb_data = NULL;
129static void gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data) {
130    GATT_WRITE_OP_CB tmp_cb = act_write_cb;
131    void* tmp_cb_data = act_write_cb_data;
132    act_write_cb = NULL;
133    act_write_cb_data = NULL;
134
135    mark_as_not_executing(conn_id);
136    gatt_execute_next_op(conn_id);
137
138    if (tmp_cb) {
139        tmp_cb(conn_id, status, handle, tmp_cb_data);
140        return;
141    }
142}
143
144static void gatt_execute_next_op(uint16_t conn_id) {
145    APPL_TRACE_DEBUG("%s:", __func__, conn_id);
146    if (gatt_op_queue.empty()) {
147        APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
148        return;
149    }
150
151    auto map_ptr = gatt_op_queue.find(conn_id);
152    if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
153        APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__, conn_id);
154        return;
155    }
156
157    if (gatt_op_queue_executing.count(conn_id)) {
158        APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__);
159        return;
160    }
161
162    gatt_op_queue_executing.insert(conn_id);
163
164    std::list<gatt_operation> &gatt_ops = map_ptr->second;
165
166    gatt_operation &op = gatt_ops.front();
167
168    if (op.type == GATT_READ_CHAR) {
169        act_read_cb = op.read_cb;
170        act_read_cb_data = op.read_cb_data;
171        BTA_GATTC_ReadCharacteristic(conn_id, op.handle, BTA_GATT_AUTH_REQ_NONE,
172                                     gatt_read_op_finished, NULL);
173
174    } else if (op.type == GATT_READ_DESC) {
175        act_read_cb = op.read_cb;
176        act_read_cb_data = op.read_cb_data;
177        BTA_GATTC_ReadCharDescr(conn_id, op.handle, BTA_GATT_AUTH_REQ_NONE,
178                                gatt_read_op_finished, NULL);
179
180    } else if (op.type == GATT_WRITE_CHAR) {
181        act_write_cb = op.write_cb;
182        act_write_cb_data = op.write_cb_data;
183        BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type, std::move(op.value),
184                                 BTA_GATT_AUTH_REQ_NONE, gatt_write_op_finished, NULL);
185
186    } else if (op.type == GATT_WRITE_DESC) {
187        act_write_cb = op.write_cb;
188        act_write_cb_data = op.write_cb_data;
189        BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
190                                 BTA_GATT_AUTH_REQ_NONE, gatt_write_op_finished, NULL);
191    }
192
193    gatt_ops.pop_front();
194}
195
196static void gatt_queue_read_op(uint8_t op_type, uint16_t conn_id, uint16_t handle,
197                               GATT_READ_OP_CB cb, void* cb_data) {
198  gatt_operation op;
199  op.type = op_type;
200  op.handle = handle;
201  op.read_cb = cb;
202  op.read_cb_data = cb_data;
203  gatt_op_queue[conn_id].push_back(op);
204  gatt_execute_next_op(conn_id);
205}
206
207static void gatt_queue_write_op(uint8_t op_type, uint16_t conn_id, uint16_t handle,
208                                vector<uint8_t> value,
209                                tBTA_GATTC_WRITE_TYPE write_type,
210                                GATT_WRITE_OP_CB cb, void* cb_data) {
211  gatt_operation op;
212  op.type = op_type;
213  op.handle = handle;
214  op.write_type = write_type;
215  op.write_cb = cb;
216  op.write_cb_data = cb_data;
217  op.value = std::move(value);
218
219  gatt_op_queue[conn_id].push_back(op);
220  gatt_execute_next_op(conn_id);
221}
222
223#if (BTA_HH_DEBUG == TRUE)
224static const char *bta_hh_le_rpt_name[4] =
225{
226    "UNKNOWN",
227    "INPUT",
228    "OUTPUT",
229    "FEATURE"
230};
231
232/*******************************************************************************
233**
234** Function         bta_hh_le_hid_report_dbg
235**
236** Description      debug function to print out all HID report available on remote
237**                  device.
238**
239** Returns          void
240**
241*******************************************************************************/
242static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb)
243{
244    APPL_TRACE_DEBUG("%s: HID Report DB", __func__);
245
246    if (!p_cb->hid_srvc.in_use)
247        return;
248
249    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[0];
250
251    for (int j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++)
252    {
253        const char * rpt_name = "Unknown";
254
255        if (!p_rpt->in_use)
256            break;
257
258        if (p_rpt->uuid == GATT_UUID_HID_REPORT)
259            rpt_name = "Report";
260        if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT)
261            rpt_name = "Boot KB Input";
262        if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT)
263            rpt_name = "Boot KB Output";
264        if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
265            rpt_name = "Boot MI Input";
266
267        APPL_TRACE_DEBUG("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [srvc_inst_id: %d] [char_inst_id: %d] [Clt_cfg: %d]",
268            rpt_name,
269            p_rpt->uuid ,
270            ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type] : "UNKNOWN"),
271            p_rpt->rpt_id,
272            p_rpt->srvc_inst_id,
273            p_rpt->char_inst_id,
274            p_rpt->client_cfg_value);
275    }
276}
277
278/*******************************************************************************
279**
280** Function         bta_hh_uuid_to_str
281**
282** Description
283**
284** Returns          void
285**
286*******************************************************************************/
287static const char *bta_hh_uuid_to_str(uint16_t uuid)
288{
289    switch(uuid)
290    {
291        case GATT_UUID_HID_INFORMATION:
292            return "GATT_UUID_HID_INFORMATION";
293        case GATT_UUID_HID_REPORT_MAP:
294            return "GATT_UUID_HID_REPORT_MAP";
295        case GATT_UUID_HID_CONTROL_POINT:
296            return "GATT_UUID_HID_CONTROL_POINT";
297        case GATT_UUID_HID_REPORT:
298            return "GATT_UUID_HID_REPORT";
299        case GATT_UUID_HID_PROTO_MODE:
300            return "GATT_UUID_HID_PROTO_MODE";
301        case GATT_UUID_HID_BT_KB_INPUT:
302            return "GATT_UUID_HID_BT_KB_INPUT";
303        case GATT_UUID_HID_BT_KB_OUTPUT:
304            return "GATT_UUID_HID_BT_KB_OUTPUT";
305        case GATT_UUID_HID_BT_MOUSE_INPUT:
306            return "GATT_UUID_HID_BT_MOUSE_INPUT";
307        case GATT_UUID_CHAR_CLIENT_CONFIG:
308            return "GATT_UUID_CHAR_CLIENT_CONFIG";
309        case GATT_UUID_EXT_RPT_REF_DESCR:
310            return "GATT_UUID_EXT_RPT_REF_DESCR";
311        case GATT_UUID_RPT_REF_DESCR:
312            return "GATT_UUID_RPT_REF_DESCR";
313        default:
314            return "Unknown UUID";
315    }
316}
317
318#endif
319/*******************************************************************************
320**
321** Function         bta_hh_le_enable
322**
323** Description      initialize LE HID related functionality
324**
325**
326** Returns          void
327**
328*******************************************************************************/
329void bta_hh_le_enable(void)
330{
331    char       app_name[LEN_UUID_128 + 1];
332    tBT_UUID    app_uuid = {LEN_UUID_128,{0}};
333    uint8_t       xx;
334
335    bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
336
337    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
338        bta_hh_cb.le_cb_index[xx]       = BTA_HH_IDX_INVALID;
339
340    memset (app_name, 0, LEN_UUID_128 + 1);
341    strncpy(app_name, "BTA HH OVER LE", LEN_UUID_128);
342
343    memcpy((void *)app_uuid.uu.uuid128, (void *)app_name, LEN_UUID_128);
344
345    BTA_GATTC_AppRegister(&app_uuid, bta_hh_gattc_callback);
346
347    return;
348}
349
350/*******************************************************************************
351**
352** Function         bta_hh_le_register_cmpl
353**
354** Description      BTA HH register with BTA GATTC completed
355**
356** Parameters:
357**
358*******************************************************************************/
359void bta_hh_le_register_cmpl(tBTA_GATTC_REG *p_reg)
360{
361    tBTA_HH_STATUS      status = BTA_HH_ERR;
362
363    if (p_reg->status == BTA_GATT_OK)
364    {
365        bta_hh_cb.gatt_if = p_reg->client_if;
366        status = BTA_HH_OK;
367    }
368    else
369        bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
370
371    /* signal BTA call back event */
372    (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
373}
374
375/*******************************************************************************
376**
377** Function         bta_hh_le_is_hh_gatt_if
378**
379** Description      Check to see if client_if is BTA HH LE GATT interface
380**
381**
382** Returns          whether it is HH GATT IF
383**
384*******************************************************************************/
385bool bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if)
386{
387    return (bta_hh_cb.gatt_if == client_if);
388}
389
390/*******************************************************************************
391**
392** Function         bta_hh_le_deregister
393**
394** Description      De-register BTA HH from BTA GATTC
395**
396**
397** Returns          void
398**
399*******************************************************************************/
400void bta_hh_le_deregister(void)
401{
402    BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if);
403}
404
405/*******************************************************************************
406**
407** Function         bta_hh_is_le_device
408**
409** Description      Check to see if the remote device is a LE only device
410**
411** Parameters:
412**
413*******************************************************************************/
414bool bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
415{
416    p_cb->is_le_device = BTM_UseLeLink (remote_bda);
417
418    return p_cb->is_le_device;
419}
420
421/*******************************************************************************
422**
423** Function         bta_hh_le_open_conn
424**
425** Description      open a GATT connection first.
426**
427** Parameters:
428**
429*******************************************************************************/
430void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
431{
432    /* update cb_index[] map */
433    p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
434    memcpy(p_cb->addr, remote_bda, BD_ADDR_LEN);
435    bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
436    p_cb->in_use = true;
437
438    BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, true, BTA_GATT_TRANSPORT_LE);
439}
440
441/*******************************************************************************
442**
443** Function         bta_hh_le_find_dev_cb_by_conn_id
444**
445** Description      Utility function find a device control block by connection ID.
446**
447*******************************************************************************/
448tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_conn_id(uint16_t conn_id)
449{
450    uint8_t   i;
451    tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
452
453    for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
454    {
455        if (p_dev_cb->in_use  && p_dev_cb->conn_id == conn_id)
456            return p_dev_cb;
457    }
458    return NULL;
459}
460
461/*******************************************************************************
462**
463** Function         bta_hh_le_find_dev_cb_by_bda
464**
465** Description      Utility function find a device control block by BD address.
466**
467*******************************************************************************/
468tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_bda(BD_ADDR bda)
469{
470    uint8_t   i;
471    tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
472
473    for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
474    {
475        if (p_dev_cb->in_use  &&
476            memcmp(p_dev_cb->addr, bda, BD_ADDR_LEN) == 0)
477            return p_dev_cb;
478    }
479    return NULL;
480}
481
482/*******************************************************************************
483**
484** Function         bta_hh_le_find_service_inst_by_battery_inst_id
485**
486** Description      find HID service instance ID by battery service instance ID
487**
488*******************************************************************************/
489uint8_t bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB *p_cb, uint8_t ba_inst_id)
490{
491    if (p_cb->hid_srvc.in_use &&
492        p_cb->hid_srvc.incl_srvc_inst == ba_inst_id)
493    {
494        return p_cb->hid_srvc.srvc_inst_id;
495    }
496    return BTA_HH_IDX_INVALID;
497}
498
499/*******************************************************************************
500**
501** Function         bta_hh_le_find_report_entry
502**
503** Description      find the report entry by service instance and report UUID and
504**                  instance ID
505**
506*******************************************************************************/
507tBTA_HH_LE_RPT * bta_hh_le_find_report_entry(tBTA_HH_DEV_CB *p_cb,
508                                             uint8_t  srvc_inst_id,  /* service instance ID */
509                                             uint16_t rpt_uuid,
510                                             uint8_t  char_inst_id)
511{
512    uint8_t   i;
513    uint8_t   hid_inst_id = srvc_inst_id;
514    tBTA_HH_LE_RPT *p_rpt;
515
516    if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
517    {
518        hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
519
520        if (hid_inst_id == BTA_HH_IDX_INVALID)
521            return NULL;
522    }
523
524    p_rpt = &p_cb->hid_srvc.report[0];
525
526    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
527    {
528        if (p_rpt->uuid == rpt_uuid &&
529            p_rpt->srvc_inst_id == srvc_inst_id &&
530            p_rpt->char_inst_id == char_inst_id)
531        {
532
533            return p_rpt;
534        }
535    }
536    return NULL;
537
538}
539
540/*******************************************************************************
541**
542** Function         bta_hh_le_find_rpt_by_idtype
543**
544** Description      find a report entry by report ID and protocol mode
545**
546** Returns          void
547**
548*******************************************************************************/
549tBTA_HH_LE_RPT * bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT*p_head, uint8_t mode,
550                                              tBTA_HH_RPT_TYPE r_type, uint8_t rpt_id)
551{
552    tBTA_HH_LE_RPT *p_rpt = p_head;
553    uint8_t   i;
554
555#if (BTA_HH_DEBUG == TRUE)
556    APPL_TRACE_DEBUG("bta_hh_le_find_rpt_by_idtype: r_type: %d rpt_id: %d", r_type, rpt_id);
557#endif
558
559    for (i = 0 ; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt++)
560    {
561        if (p_rpt->in_use && p_rpt->rpt_id == rpt_id && r_type == p_rpt->rpt_type)
562        {
563            /* return battery report w/o condition */
564            if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
565                return p_rpt;
566
567            if (mode == BTA_HH_PROTO_RPT_MODE && p_rpt->uuid == GATT_UUID_HID_REPORT)
568                return p_rpt;
569
570            if ( mode ==BTA_HH_PROTO_BOOT_MODE &&
571                (p_rpt->uuid >= GATT_UUID_HID_BT_KB_INPUT && p_rpt->uuid <= GATT_UUID_HID_BT_MOUSE_INPUT))
572                return p_rpt;
573        }
574    }
575    return NULL;
576}
577
578/*******************************************************************************
579**
580** Function         bta_hh_le_find_alloc_report_entry
581**
582** Description      find or allocate a report entry in the HID service report list.
583**
584*******************************************************************************/
585tBTA_HH_LE_RPT * bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB *p_cb,
586                                                   uint8_t srvc_inst_id,
587                                                   uint16_t rpt_uuid,
588                                                   uint8_t  inst_id)
589{
590    uint8_t   i, hid_inst_id = srvc_inst_id;
591    tBTA_HH_LE_RPT *p_rpt;
592
593    if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
594    {
595        hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
596
597        if (hid_inst_id == BTA_HH_IDX_INVALID)
598            return NULL;
599    }
600    p_rpt = &p_cb->hid_srvc.report[0];
601
602    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
603    {
604        if (!p_rpt->in_use ||
605            (p_rpt->uuid == rpt_uuid &&
606             p_rpt->srvc_inst_id == srvc_inst_id &&
607             p_rpt->char_inst_id == inst_id))
608        {
609            if (!p_rpt->in_use)
610            {
611                p_rpt->in_use   = true;
612                p_rpt->index    = i;
613                p_rpt->srvc_inst_id = srvc_inst_id;
614                p_rpt->char_inst_id = inst_id;
615                p_rpt->uuid     = rpt_uuid;
616
617                /* assign report type */
618                for (i = 0; i < BTA_LE_HID_RTP_UUID_MAX; i ++)
619                {
620                    if (bta_hh_uuid_to_rtp_type[i][0] == rpt_uuid)
621                    {
622                        p_rpt->rpt_type = (tBTA_HH_RPT_TYPE)bta_hh_uuid_to_rtp_type[i][1];
623
624                        if (rpt_uuid == GATT_UUID_HID_BT_KB_INPUT || rpt_uuid == GATT_UUID_HID_BT_KB_OUTPUT)
625                            p_rpt->rpt_id = BTA_HH_KEYBD_RPT_ID;
626
627                        if (rpt_uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
628                            p_rpt->rpt_id = BTA_HH_MOUSE_RPT_ID;
629
630                        break;
631                    }
632                }
633            }
634            return p_rpt;
635        }
636    }
637    return NULL;
638}
639
640static tBTA_GATTC_DESCRIPTOR *find_descriptor_by_short_uuid(uint16_t conn_id,
641                                                     uint16_t char_handle,
642                                                     uint16_t short_uuid) {
643    const tBTA_GATTC_CHARACTERISTIC *p_char =
644                BTA_GATTC_GetCharacteristic(conn_id, char_handle);
645
646    if (!p_char) {
647        LOG_WARN(LOG_TAG, "%s No such characteristic: %d", __func__, char_handle);
648        return NULL;
649    }
650
651    if (!p_char->descriptors || list_is_empty(p_char->descriptors))
652        return NULL;
653
654    for (list_node_t *dn = list_begin(p_char->descriptors);
655         dn != list_end(p_char->descriptors); dn = list_next(dn)) {
656        tBTA_GATTC_DESCRIPTOR *p_desc = (tBTA_GATTC_DESCRIPTOR*) list_node(dn);
657
658        if (p_char->uuid.len == LEN_UUID_16 &&
659            p_desc->uuid.uu.uuid16 == short_uuid)
660            return p_desc;
661    }
662
663    return NULL;
664}
665
666/*******************************************************************************
667**
668** Function         bta_hh_le_read_char_descriptor
669**
670** Description      read characteristic descriptor
671**
672*******************************************************************************/
673static tBTA_HH_STATUS bta_hh_le_read_char_descriptor(tBTA_HH_DEV_CB *p_cb, uint16_t char_handle,
674                                                     uint16_t short_uuid, GATT_READ_OP_CB cb,
675                                                     void* cb_data)
676{
677    const tBTA_GATTC_DESCRIPTOR *p_desc =
678        find_descriptor_by_short_uuid(p_cb->conn_id, char_handle, short_uuid);
679    if (!p_desc)
680        return BTA_HH_ERR;
681
682    gatt_queue_read_op(GATT_READ_DESC, p_cb->conn_id, p_desc->handle, cb, cb_data);
683    return BTA_HH_OK;
684}
685
686/*******************************************************************************
687**
688** Function         bta_hh_le_save_report_ref
689**
690** Description      save report reference information and move to next one.
691**
692** Parameters:
693**
694*******************************************************************************/
695void bta_hh_le_save_report_ref(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT  *p_rpt,
696                            tGATT_STATUS status, uint8_t *value, uint16_t len)
697{
698    if (status == BTA_GATT_INSUF_AUTHENTICATION)
699    {
700        /* close connection right away */
701        p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
702        /* close the connection and report service discovery complete with error */
703        bta_hh_le_api_disc_act(p_dev_cb);
704        return;
705    }
706
707    /* if the length of the descriptor value is right, parse it */
708    if (status == BTA_GATT_OK && len == 2)
709    {
710        uint8_t *pp = value;
711
712        STREAM_TO_UINT8(p_rpt->rpt_id, pp);
713        STREAM_TO_UINT8(p_rpt->rpt_type, pp);
714
715        if (p_rpt->rpt_type > BTA_HH_RPTT_FEATURE) /* invalid report type */
716            p_rpt->rpt_type = BTA_HH_RPTT_RESRV;
717
718#if (BTA_HH_DEBUG == TRUE)
719        APPL_TRACE_DEBUG("%s: report ID: %d", __func__, p_rpt->rpt_id);
720#endif
721        tBTA_HH_RPT_CACHE_ENTRY rpt_entry;
722        rpt_entry.rpt_id    = p_rpt->rpt_id;
723        rpt_entry.rpt_type  = p_rpt->rpt_type;
724        rpt_entry.rpt_uuid  = p_rpt->uuid;
725        rpt_entry.srvc_inst_id = p_rpt->srvc_inst_id;
726        rpt_entry.char_inst_id = p_rpt->char_inst_id;
727
728        bta_hh_le_co_rpt_info(p_dev_cb->addr,
729                              &rpt_entry,
730                              p_dev_cb->app_id);
731    }
732
733    if (p_rpt->index < BTA_HH_LE_RPT_MAX - 1)
734        p_rpt ++;
735    else
736        p_rpt = NULL;
737}
738
739/*******************************************************************************
740**
741** Function         bta_hh_le_register_input_notif
742**
743** Description      Register for all notifications for the report applicable
744**                  for the protocol mode.
745**
746** Parameters:
747**
748*******************************************************************************/
749void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, uint8_t proto_mode, bool register_ba)
750{
751    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
752
753#if (BTA_HH_DEBUG == TRUE)
754    APPL_TRACE_DEBUG("%s: bta_hh_le_register_input_notif mode: %d", __func__, proto_mode);
755#endif
756
757    for (int i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
758    {
759        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
760        {
761
762            if (register_ba && p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
763            {
764                BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
765                                                   p_rpt->char_inst_id);
766            }
767            /* boot mode, deregister report input notification */
768            else if (proto_mode == BTA_HH_PROTO_BOOT_MODE)
769            {
770                if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
771                    p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
772                {
773                    APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__, p_rpt->rpt_id);
774                    BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
775                                                         p_rpt->char_inst_id);
776                }
777                /* register boot reports notification */
778                else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
779                         p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
780                {
781                    APPL_TRACE_DEBUG("%s <--- Register Boot Report ID: %d", __func__, p_rpt->rpt_id);
782                    BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
783                                                       p_rpt->char_inst_id);
784                }
785            }
786            else if (proto_mode == BTA_HH_PROTO_RPT_MODE)
787            {
788                if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
789                    p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
790                    p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
791                {
792
793                    APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__, p_rpt->rpt_id);
794                    BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
795                                                         p_rpt->char_inst_id);
796                }
797                else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
798                         p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
799                {
800                    APPL_TRACE_DEBUG("%s <--- Register Report ID: %d", __func__, p_rpt->rpt_id);
801                    BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
802                                                       p_rpt->char_inst_id);
803                }
804            }
805            /*
806            else unknow protocol mode */
807        }
808    }
809}
810
811/*******************************************************************************
812**
813** Function         bta_hh_le_deregister_input_notif
814**
815** Description      Deregister all notifications
816**
817*******************************************************************************/
818void bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB *p_dev_cb)
819{
820    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
821
822    for (uint8_t i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++)
823    {
824        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
825        {
826            if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
827                p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
828            {
829                APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__, p_rpt->rpt_id);
830                BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
831                                                    p_rpt->char_inst_id);
832            }
833            else if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
834                p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
835                p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
836            {
837                APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__, p_rpt->rpt_id);
838                BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
839                                                    p_rpt->char_inst_id);
840            }
841        }
842    }
843}
844
845
846/*******************************************************************************
847**
848** Function         bta_hh_le_open_cmpl
849**
850** Description      HID over GATT connection sucessfully opened
851**
852*******************************************************************************/
853void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
854{
855    if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
856    {
857#if (BTA_HH_DEBUG == TRUE)
858        bta_hh_le_hid_report_dbg(p_cb);
859#endif
860        bta_hh_le_register_input_notif(p_cb, p_cb->mode, true);
861        bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
862
863#if (BTA_HH_LE_RECONN == TRUE)
864        if (p_cb->status == BTA_HH_OK)
865        {
866            bta_hh_le_add_dev_bg_conn(p_cb, true);
867        }
868#endif
869    }
870}
871
872/*******************************************************************************
873**
874** Function         bta_hh_le_write_ccc
875**
876** Description      Utility function to find and write client configuration of
877**                  a characteristic
878**
879*******************************************************************************/
880bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB *p_cb,
881                                     uint8_t char_handle,
882                                     uint16_t clt_cfg_value,
883                                     GATT_WRITE_OP_CB cb,
884                                     void* cb_data)
885{
886    tBTA_GATTC_DESCRIPTOR *p_desc = find_descriptor_by_short_uuid(p_cb->conn_id,
887                                       char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
888    if (!p_desc)
889        return false;
890
891    vector<uint8_t> value(2);
892    uint8_t* ptr = value.data();
893    UINT16_TO_STREAM(ptr, clt_cfg_value);
894
895    gatt_queue_write_op(GATT_WRITE_DESC, p_cb->conn_id, p_desc->handle,
896                        std::move(value), BTA_GATTC_TYPE_WRITE, cb, cb_data);
897    return true;
898}
899
900bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb);
901
902static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data) {
903    uint8_t   srvc_inst_id, hid_inst_id;
904
905    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
906    const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(conn_id, handle);
907
908    uint16_t char_uuid = p_desc->characteristic->uuid.uu.uuid16;
909
910    srvc_inst_id = p_desc->characteristic->service->handle;
911    hid_inst_id = srvc_inst_id;
912    switch (char_uuid)
913    {
914    case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
915        hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
916        /* FALLTHROUGH */
917    case GATT_UUID_HID_BT_KB_INPUT:
918    case GATT_UUID_HID_BT_MOUSE_INPUT:
919    case GATT_UUID_HID_REPORT:
920        if (status == BTA_GATT_OK)
921            p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
922                    BTA_GATT_CLT_CONFIG_NOTIFICATION;
923        p_dev_cb->clt_cfg_idx ++;
924        bta_hh_le_write_rpt_clt_cfg(p_dev_cb);
925        break;
926
927    default:
928        APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", char_uuid);
929    }
930}
931/*******************************************************************************
932**
933** Function         bta_hh_le_write_rpt_clt_cfg
934**
935** Description      write client configuration. This is only for input report
936**                  enable all input notification upon connection open.
937**
938*******************************************************************************/
939bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb)
940{
941    uint8_t           i;
942    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[p_cb->clt_cfg_idx];
943
944    for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
945    {
946        /* enable notification for all input report, regardless mode */
947        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
948        {
949            if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id,
950                                    BTA_GATT_CLT_CONFIG_NOTIFICATION,
951                                    write_rpt_ctl_cfg_cb, p_cb))
952            {
953                p_cb->clt_cfg_idx = i;
954                return true;
955            }
956        }
957    }
958    p_cb->clt_cfg_idx = 0;
959
960    /* client configuration is completed, send open callback */
961    if (p_cb->state == BTA_HH_W4_CONN_ST)
962    {
963        p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
964
965        bta_hh_le_open_cmpl(p_cb);
966    }
967    return false;
968}
969
970static void write_proto_mode_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data) {
971    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*) data;
972
973    if (p_dev_cb->state == BTA_HH_CONN_ST) {
974        /* Set protocol finished in CONN state*/
975
976        uint16_t cb_evt = p_dev_cb->w4_evt;
977        if (cb_evt == 0)
978            return;
979
980        tBTA_HH_CBDATA      cback_data;
981
982        cback_data.handle  = p_dev_cb->hid_handle;
983        cback_data.status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR;
984
985        if (status == BTA_GATT_OK)
986            bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, false);
987
988        p_dev_cb->w4_evt = 0;
989        (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
990    } else if (p_dev_cb->state == BTA_HH_W4_CONN_ST) {
991        p_dev_cb->status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
992
993        if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) == 0)
994            bta_hh_le_open_cmpl(p_dev_cb);
995    }
996}
997
998/*******************************************************************************
999**
1000** Function         bta_hh_le_set_protocol_mode
1001**
1002** Description      Set remote device protocol mode.
1003**
1004*******************************************************************************/
1005bool bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
1006{
1007    tBTA_HH_CBDATA      cback_data;
1008
1009    APPL_TRACE_DEBUG("%s attempt mode: %s", __func__,
1010                     (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
1011
1012    cback_data.handle  = p_cb->hid_handle;
1013    /* boot mode is not supported in the remote device */
1014    if (p_cb->hid_srvc.proto_mode_handle == 0)
1015    {
1016        p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
1017
1018        if (mode == BTA_HH_PROTO_BOOT_MODE)
1019        {
1020            APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
1021            cback_data.status = BTA_HH_ERR;
1022        }
1023        else
1024        {
1025            /* if set to report mode, need to de-register all input report notification */
1026            bta_hh_le_register_input_notif(p_cb, p_cb->mode, false);
1027            cback_data.status = BTA_HH_OK;
1028        }
1029        if (p_cb->state == BTA_HH_W4_CONN_ST)
1030        {
1031            p_cb->status = (cback_data.status == BTA_HH_OK)? BTA_HH_OK: BTA_HH_ERR_PROTO;
1032        }
1033        else
1034            (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
1035    } else if (p_cb->mode != mode) {
1036        p_cb->mode = mode;
1037        mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
1038
1039        gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle,
1040                            { mode }, BTA_GATTC_TYPE_WRITE_NO_RSP, write_proto_mode_cb, p_cb);
1041        return true;
1042    }
1043
1044    return false;
1045}
1046
1047/*******************************************************************************
1048** Function         get_protocol_mode_cb
1049**
1050** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
1051**                  with the protocol mode.
1052**
1053*******************************************************************************/
1054static void get_protocol_mode_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
1055                                 uint8_t *value, void* data) {
1056    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB *)data;
1057    tBTA_HH_HSDATA      hs_data;
1058
1059    hs_data.status  = BTA_HH_ERR;
1060    hs_data.handle  = p_dev_cb->hid_handle;
1061    hs_data.rsp_data.proto_mode = p_dev_cb->mode;
1062
1063    if (status == BTA_GATT_OK && len)
1064    {
1065        hs_data.status  = BTA_HH_OK;
1066        /* match up BTE/BTA report/boot mode def*/
1067        hs_data.rsp_data.proto_mode = *(value);
1068        /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
1069        if (hs_data.rsp_data.proto_mode == 0)
1070            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
1071        else
1072            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1073
1074        p_dev_cb->mode = hs_data.rsp_data.proto_mode;
1075    }
1076
1077#if (BTA_HH_DEBUG == TRUE)
1078    APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
1079                        (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
1080#endif
1081
1082    p_dev_cb->w4_evt = 0;
1083    (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1084}
1085
1086/*******************************************************************************
1087**
1088** Function         bta_hh_le_get_protocol_mode
1089**
1090** Description      Get remote device protocol mode.
1091**
1092*******************************************************************************/
1093void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
1094{
1095    tBTA_HH_HSDATA    hs_data;
1096    p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
1097
1098    if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
1099        gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle,
1100                           get_protocol_mode_cb, p_cb);
1101        return;
1102    }
1103
1104    /* no service support protocol_mode, by default report mode */
1105    hs_data.status  = BTA_HH_OK;
1106    hs_data.handle  = p_cb->hid_handle;
1107    hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1108    p_cb->w4_evt = 0;
1109    (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1110}
1111
1112/*******************************************************************************
1113**
1114** Function         bta_hh_le_dis_cback
1115**
1116** Description      DIS read complete callback
1117**
1118** Parameters:
1119**
1120*******************************************************************************/
1121void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
1122{
1123    tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
1124
1125
1126    if (p_cb == NULL || p_dis_value == NULL)
1127    {
1128        APPL_TRACE_ERROR("received unexpected/error DIS callback");
1129        return;
1130    }
1131
1132    p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1133    /* plug in the PnP info for this device */
1134    if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT)
1135    {
1136#if (BTA_HH_DEBUG == TRUE)
1137        APPL_TRACE_DEBUG("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
1138                p_dis_value->pnp_id.product_id,
1139                p_dis_value->pnp_id.vendor_id,
1140                p_dis_value->pnp_id.product_version);
1141#endif
1142        p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
1143        p_cb->dscp_info.vendor_id  = p_dis_value->pnp_id.vendor_id;
1144        p_cb->dscp_info.version    = p_dis_value->pnp_id.product_version;
1145    }
1146    bta_hh_le_open_cmpl(p_cb);
1147}
1148
1149/*******************************************************************************
1150**
1151** Function         bta_hh_le_pri_service_discovery
1152**
1153** Description      Initialize GATT discovery on the remote LE HID device by opening
1154**                  a GATT connection first.
1155**
1156** Parameters:
1157**
1158*******************************************************************************/
1159void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
1160{
1161    tBT_UUID        pri_srvc;
1162
1163    bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
1164
1165    p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
1166
1167    /* read DIS info */
1168    if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT))
1169    {
1170        APPL_TRACE_ERROR("read DIS failed");
1171        p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1172    }
1173
1174    /* in parallel */
1175    /* start primary service discovery for HID service */
1176    pri_srvc.len        = LEN_UUID_16;
1177    pri_srvc.uu.uuid16  = UUID_SERVCLASS_LE_HID;
1178    BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
1179    return;
1180}
1181
1182/*******************************************************************************
1183**
1184** Function         bta_hh_le_encrypt_cback
1185**
1186** Description      link encryption complete callback for bond verification.
1187**
1188** Returns          None
1189**
1190*******************************************************************************/
1191void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
1192                                    void *p_ref_data, tBTM_STATUS result)
1193{
1194    uint8_t   idx = bta_hh_find_cb(bd_addr);
1195    tBTA_HH_DEV_CB *p_dev_cb;
1196    UNUSED(p_ref_data);
1197    UNUSED (transport);
1198
1199    if (idx != BTA_HH_IDX_INVALID)
1200        p_dev_cb = &bta_hh_cb.kdev[idx];
1201    else
1202    {
1203        APPL_TRACE_ERROR("unexpected encryption callback, ignore");
1204        return;
1205    }
1206    p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
1207    p_dev_cb->reason = result;
1208
1209    bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1210}
1211
1212/*******************************************************************************
1213**
1214** Function         bta_hh_security_cmpl
1215**
1216** Description      Security check completed, start the service discovery
1217**                  if no cache available, otherwise report connection open completed
1218**
1219** Parameters:
1220**
1221*******************************************************************************/
1222void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1223{
1224    UNUSED(p_buf);
1225
1226    APPL_TRACE_DEBUG("%s", __func__);
1227    if (p_cb->status == BTA_HH_OK)
1228    {
1229        if (!p_cb->hid_srvc.in_use)
1230        {
1231            APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
1232
1233            /* start loading the cache if not in stack */
1234            //TODO(jpawlowski): cache storage is broken, fix it
1235            // tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
1236            // uint8_t                       num_rpt = 0;
1237            // if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
1238            // {
1239            //     bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
1240            // }
1241        }
1242        /*  discovery has been done for HID service */
1243        if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use)
1244        {
1245            APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
1246            /* configure protocol mode */
1247            if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == false)
1248            {
1249                bta_hh_le_open_cmpl(p_cb);
1250            }
1251        }
1252        /* start primary service discovery for HID service */
1253        else
1254        {
1255            APPL_TRACE_DEBUG("%s: Starting service discovery", __func__);
1256            bta_hh_le_pri_service_discovery(p_cb);
1257        }
1258    }
1259    else
1260    {
1261        APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
1262                __func__, p_cb->status, p_cb->reason);
1263        if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
1264            bta_hh_le_api_disc_act(p_cb);
1265    }
1266}
1267
1268/*******************************************************************************
1269**
1270** Function         bta_hh_le_notify_enc_cmpl
1271**
1272** Description      process GATT encryption complete event
1273**
1274** Returns
1275**
1276*******************************************************************************/
1277void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1278{
1279    if (p_cb == NULL || p_cb->security_pending == false ||
1280        p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
1281    {
1282        return;
1283    }
1284
1285    p_cb->security_pending = false;
1286    bta_hh_start_security(p_cb, NULL);
1287}
1288
1289/*******************************************************************************
1290**
1291** Function         bta_hh_clear_service_cache
1292**
1293** Description      clear the service cache
1294**
1295** Parameters:
1296**
1297*******************************************************************************/
1298void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
1299{
1300    tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc;
1301
1302    p_cb->app_id = 0;
1303    p_cb->dscp_info.descriptor.dsc_list = NULL;
1304
1305    osi_free_and_reset((void **)&p_hid_srvc->rpt_map);
1306    memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
1307}
1308
1309/*******************************************************************************
1310**
1311** Function         bta_hh_start_security
1312**
1313** Description      start the security check of the established connection
1314**
1315** Parameters:
1316**
1317*******************************************************************************/
1318void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1319{
1320    uint8_t           sec_flag=0;
1321    tBTM_SEC_DEV_REC  *p_dev_rec;
1322    UNUSED(p_buf);
1323
1324    p_dev_rec = btm_find_dev(p_cb->addr);
1325    if (p_dev_rec)
1326    {
1327        if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
1328            p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
1329        {
1330            /* if security collision happened, wait for encryption done */
1331            p_cb->security_pending = true;
1332            return;
1333        }
1334    }
1335
1336    /* verify bond */
1337    BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
1338
1339    /* if link has been encrypted */
1340    if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
1341    {
1342        bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1343    }
1344    /* if bonded and link not encrypted */
1345    else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
1346    {
1347        sec_flag = BTM_BLE_SEC_ENCRYPT;
1348        p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1349        BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
1350    }
1351    /* unbonded device, report security error here */
1352    else if (p_cb->sec_mask != BTA_SEC_NONE)
1353    {
1354        sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
1355        p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1356        bta_hh_clear_service_cache(p_cb);
1357        BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
1358    }
1359    /* otherwise let it go through */
1360    else
1361    {
1362        bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1363    }
1364
1365
1366}
1367
1368/*******************************************************************************
1369**
1370** Function         bta_hh_gatt_open
1371**
1372** Description      process GATT open event.
1373**
1374** Parameters:
1375**
1376*******************************************************************************/
1377void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1378{
1379    tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
1380    uint8_t           *p2;
1381    tHID_STATUS     status = BTA_HH_ERR;
1382
1383    /* if received invalid callback data , ignore it */
1384    if (p_cb == NULL || p_data == NULL)
1385        return;
1386
1387    p2 = p_data->remote_bda;
1388
1389    APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
1390                      ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
1391                      ((p2[4])<<8)+ p2[5],p_data->status);
1392
1393    if (p_data->status == BTA_GATT_OK)
1394    {
1395        p_cb->is_le_device  = true;
1396        p_cb->in_use    = true;
1397        p_cb->conn_id   = p_data->conn_id;
1398        p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
1399
1400        bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
1401
1402        gatt_op_queue_clean(p_cb->conn_id);
1403
1404#if (BTA_HH_DEBUG == TRUE)
1405        APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
1406#endif
1407
1408        bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
1409
1410    }
1411    else /* open failure */
1412    {
1413        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
1414    }
1415
1416}
1417
1418/*******************************************************************************
1419**
1420** Function         bta_hh_le_close
1421**
1422** Description      This function process the GATT close event and post it as a
1423**                  BTA HH internal event
1424**
1425** Parameters:
1426**
1427*******************************************************************************/
1428void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
1429{
1430    tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
1431    uint16_t  sm_event = BTA_HH_GATT_CLOSE_EVT;
1432
1433    if (p_dev_cb != NULL) {
1434        tBTA_HH_LE_CLOSE *p_buf =
1435            (tBTA_HH_LE_CLOSE *)osi_malloc(sizeof(tBTA_HH_LE_CLOSE));
1436        p_buf->hdr.event = sm_event;
1437        p_buf->hdr.layer_specific = (uint16_t)p_dev_cb->hid_handle;
1438        p_buf->conn_id = p_data->conn_id;
1439        p_buf->reason = p_data->reason;
1440
1441        p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
1442        p_dev_cb->security_pending = false;
1443        bta_sys_sendmsg(p_buf);
1444    }
1445}
1446
1447/*******************************************************************************
1448**
1449** Function         bta_hh_le_gatt_disc_cmpl
1450**
1451** Description      Check to see if the remote device is a LE only device
1452**
1453** Parameters:
1454**
1455*******************************************************************************/
1456void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
1457{
1458    APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
1459
1460    /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
1461    if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
1462    {
1463        /* assign a special APP ID temp, since device type unknown */
1464        p_cb->app_id = BTA_HH_APP_ID_LE;
1465
1466        /* set report notification configuration */
1467        p_cb->clt_cfg_idx = 0;
1468        bta_hh_le_write_rpt_clt_cfg(p_cb);
1469    }
1470    else /* error, close the GATT connection */
1471    {
1472        /* close GATT connection if it's on */
1473        bta_hh_le_api_disc_act(p_cb);
1474    }
1475}
1476
1477static void read_hid_info_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
1478                             uint8_t *value, void* data) {
1479    if (status != BTA_GATT_OK) {
1480        APPL_TRACE_ERROR("%s: error: %d",  __func__, status);
1481        return;
1482    }
1483
1484    if (len != 4) {
1485        APPL_TRACE_ERROR("%s: wrong length: %d",  __func__, len);
1486        return;
1487    }
1488
1489    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1490    uint8_t *pp = value;
1491    /* save device information */
1492    STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
1493    STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
1494    STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
1495}
1496
1497static void read_hid_report_map_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1498                                   uint16_t len, uint8_t *value, void* data) {
1499    if (status != BTA_GATT_OK) {
1500        APPL_TRACE_ERROR("%s: error reading characteristic: %d",  __func__, status);
1501        return;
1502    }
1503
1504    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1505    tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc;
1506
1507    osi_free_and_reset((void **)&p_srvc->rpt_map);
1508
1509    if (len > 0) {
1510        p_srvc->rpt_map = (uint8_t *)osi_malloc(len);
1511
1512        uint8_t *pp = value;
1513        STREAM_TO_ARRAY(p_srvc->rpt_map, pp, len);
1514        p_srvc->descriptor.dl_len = len;
1515        p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map;
1516    }
1517}
1518
1519static void read_ext_rpt_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1520                                     uint16_t len, uint8_t *value, void* data) {
1521    if (status != BTA_GATT_OK) {
1522        APPL_TRACE_ERROR("%s: error: %d",  __func__, status);
1523        return;
1524    }
1525
1526    /* if the length of the descriptor value is right, parse it assume it's a 16 bits UUID */
1527    if (len != LEN_UUID_16) {
1528        APPL_TRACE_ERROR("%s: we support only 16bit UUID: %d",  __func__, len);
1529        return;
1530    }
1531
1532    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1533    uint8_t *pp = value;
1534
1535    STREAM_TO_UINT16(p_dev_cb->hid_srvc.ext_rpt_ref, pp);
1536
1537#if (BTA_HH_DEBUG == TRUE)
1538    APPL_TRACE_DEBUG("%s: External Report Reference UUID 0x%04x", __func__,
1539            p_dev_cb->hid_srvc.ext_rpt_ref);
1540#endif
1541}
1542
1543static void read_report_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1544                                    uint16_t len, uint8_t *value, void* data) {
1545    if (status != BTA_GATT_OK) {
1546        APPL_TRACE_ERROR("%s: error: %d",  __func__, status);
1547        return;
1548    }
1549
1550    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1551    const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(conn_id, handle);
1552
1553    tBTA_HH_LE_RPT  *p_rpt;
1554    if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1555                                        p_desc->characteristic->service->handle,
1556                                        GATT_UUID_HID_REPORT,
1557                                        p_desc->characteristic->handle)))
1558        bta_hh_le_save_report_ref(p_dev_cb, p_rpt, status, value, len);
1559}
1560
1561
1562
1563void read_pref_conn_params_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1564                              uint16_t len, uint8_t *value, void* data) {
1565    if (status != BTA_GATT_OK) {
1566        APPL_TRACE_ERROR("%s: error: %d",  __func__, status);
1567        return;
1568    }
1569
1570    if (len != 8) {
1571        APPL_TRACE_ERROR("%s: we support only 16bit UUID: %d",  __func__, len);
1572        return;
1573    }
1574
1575    //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
1576    uint8_t *pp = value;
1577    uint16_t min, max, latency, tout;
1578    STREAM_TO_UINT16(min, pp);
1579    STREAM_TO_UINT16(max, pp);
1580    STREAM_TO_UINT16(latency, pp);
1581    STREAM_TO_UINT16(tout, pp);
1582
1583    // Make sure both min, and max are bigger than 11.25ms, lower values can introduce
1584    // audio issues if A2DP is also active.
1585    if (min < BTM_BLE_CONN_INT_MIN_LIMIT)
1586        min = BTM_BLE_CONN_INT_MIN_LIMIT;
1587    if (max < BTM_BLE_CONN_INT_MIN_LIMIT)
1588        max = BTM_BLE_CONN_INT_MIN_LIMIT;
1589
1590    // If the device has no preferred connection timeout, use the default.
1591    if (tout == BTM_BLE_CONN_PARAM_UNDEF)
1592        tout = BTM_BLE_CONN_TIMEOUT_DEF;
1593
1594    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1595    BTM_BleSetPrefConnParams(p_dev_cb->addr, min, max, latency, tout);
1596    L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
1597}
1598
1599/*******************************************************************************
1600**
1601** Function         bta_hh_le_search_hid_chars
1602**
1603** Description      This function discover all characteristics a service and
1604**                  all descriptors available.
1605**
1606** Parameters:
1607**
1608*******************************************************************************/
1609static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service)
1610{
1611    tBTA_HH_LE_RPT *p_rpt;
1612
1613    for (list_node_t *cn = list_begin(service->characteristics);
1614         cn != list_end(service->characteristics); cn = list_next(cn)) {
1615        tBTA_GATTC_CHARACTERISTIC *p_char = (tBTA_GATTC_CHARACTERISTIC*) list_node(cn);
1616
1617        if (p_char->uuid.len != LEN_UUID_16)
1618            continue;
1619
1620        LOG_DEBUG(LOG_TAG, "%s: %s 0x%04d", __func__, bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
1621                  p_char->uuid.uu.uuid16);
1622
1623        switch (p_char->uuid.uu.uuid16)
1624        {
1625        case GATT_UUID_HID_CONTROL_POINT:
1626            p_dev_cb->hid_srvc.control_point_handle = p_char->handle;
1627            break;
1628        case GATT_UUID_HID_INFORMATION:
1629            /* only one instance per HID service */
1630            gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle, read_hid_info_cb,
1631                               p_dev_cb);
1632            break;
1633        case GATT_UUID_HID_REPORT_MAP:
1634            /* only one instance per HID service */
1635            gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle,
1636                               read_hid_report_map_cb, p_dev_cb);
1637            /* descriptor is optional */
1638            bta_hh_le_read_char_descriptor(p_dev_cb, p_char->handle,
1639                                   GATT_UUID_EXT_RPT_REF_DESCR, read_ext_rpt_ref_desc_cb, p_dev_cb);
1640            break;
1641
1642        case GATT_UUID_HID_REPORT:
1643            p_rpt = bta_hh_le_find_alloc_report_entry(p_dev_cb,
1644                                              p_dev_cb->hid_srvc.srvc_inst_id,
1645                                              GATT_UUID_HID_REPORT,
1646                                              p_char->handle);
1647            if (p_rpt == NULL) {
1648                APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
1649                break;
1650            }
1651
1652            if (p_rpt->rpt_type != BTA_HH_RPTT_INPUT)
1653                break;
1654
1655            bta_hh_le_read_char_descriptor(p_dev_cb, p_char->handle, GATT_UUID_RPT_REF_DESCR,
1656                                       read_report_ref_desc_cb, p_dev_cb);
1657            break;
1658
1659        /* found boot mode report types */
1660        case GATT_UUID_HID_BT_KB_OUTPUT:
1661        case GATT_UUID_HID_BT_MOUSE_INPUT:
1662        case GATT_UUID_HID_BT_KB_INPUT:
1663            if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1664                                      service->handle,
1665                                      p_char->uuid.uu.uuid16,
1666                                      p_char->handle) == NULL)
1667                APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
1668
1669            break;
1670
1671        default:
1672            APPL_TRACE_DEBUG("%s: not processing %s 0x%04d", __func__,
1673                             bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
1674                             p_char->uuid.uu.uuid16);
1675        }
1676    }
1677
1678    /* Make sure PROTO_MODE is processed as last */
1679    for (list_node_t *cn = list_begin(service->characteristics);
1680         cn != list_end(service->characteristics); cn = list_next(cn)) {
1681        tBTA_GATTC_CHARACTERISTIC *p_char = (tBTA_GATTC_CHARACTERISTIC*) list_node(cn);
1682
1683        if (p_char->uuid.len != LEN_UUID_16 &&
1684           p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
1685            p_dev_cb->hid_srvc.proto_mode_handle = p_char->handle;
1686            bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1687            break;
1688        }
1689    }
1690}
1691
1692/*******************************************************************************
1693**
1694** Function         bta_hh_le_srvc_search_cmpl
1695**
1696** Description      This function process the GATT service search complete.
1697**
1698** Parameters:
1699**
1700*******************************************************************************/
1701void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
1702{
1703    tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
1704
1705    /* service search exception or no HID service is supported on remote */
1706    if (p_dev_cb == NULL)
1707        return;
1708
1709    if (p_data->status != BTA_GATT_OK)
1710    {
1711        p_dev_cb->status = BTA_HH_ERR_SDP;
1712        /* close the connection and report service discovery complete with error */
1713        bta_hh_le_api_disc_act(p_dev_cb);
1714        return;
1715    }
1716
1717    const list_t *services = BTA_GATTC_GetServices(p_data->conn_id);
1718
1719    bool have_hid = false;
1720    for (list_node_t *sn = list_begin(services);
1721         sn != list_end(services); sn = list_next(sn)) {
1722        tBTA_GATTC_SERVICE *service = (tBTA_GATTC_SERVICE*) list_node(sn);
1723
1724        if (service->uuid.uu.uuid16 == UUID_SERVCLASS_LE_HID &&
1725            service->is_primary && !have_hid) {
1726            have_hid = true;
1727
1728            /* found HID primamry service */
1729            p_dev_cb->hid_srvc.in_use = true;
1730            p_dev_cb->hid_srvc.srvc_inst_id = service->handle;
1731            p_dev_cb->hid_srvc.proto_mode_handle = 0;
1732            p_dev_cb->hid_srvc.control_point_handle = 0;
1733
1734            bta_hh_le_search_hid_chars(p_dev_cb, service);
1735
1736            APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__,
1737                             p_dev_cb->hid_srvc.srvc_inst_id);
1738        } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_SCAN_PARAM) {
1739            p_dev_cb->scan_refresh_char_handle = 0;
1740
1741            for (list_node_t *cn = list_begin(service->characteristics);
1742                 cn != list_end(service->characteristics); cn = list_next(cn)) {
1743                tBTA_GATTC_CHARACTERISTIC *p_char = (tBTA_GATTC_CHARACTERISTIC*) list_node(cn);
1744                if (p_char->uuid.len == LEN_UUID_16 &&
1745                    p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_REFRESH) {
1746
1747                    p_dev_cb->scan_refresh_char_handle = p_char->handle;
1748
1749                    if (p_char->properties & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
1750                        p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
1751                    else
1752                        p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
1753
1754                    break;
1755                }
1756            }
1757        } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER) {
1758            //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
1759            for (list_node_t *cn = list_begin(service->characteristics);
1760                 cn != list_end(service->characteristics); cn = list_next(cn)) {
1761                tBTA_GATTC_CHARACTERISTIC *p_char = (tBTA_GATTC_CHARACTERISTIC*) list_node(cn);
1762                if (p_char->uuid.len == LEN_UUID_16 &&
1763                    p_char->uuid.uu.uuid16 == GATT_UUID_GAP_PREF_CONN_PARAM) {
1764
1765                    /* read the char value */
1766                    gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle,
1767                                       read_pref_conn_params_cb, p_dev_cb);
1768
1769                    break;
1770                }
1771            }
1772        }
1773    }
1774
1775    bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
1776}
1777
1778/*******************************************************************************
1779**
1780** Function         bta_hh_le_input_rpt_notify
1781**
1782** Description      process the notificaton event, most likely for input report.
1783**
1784** Parameters:
1785**
1786*******************************************************************************/
1787void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
1788{
1789    tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
1790    uint8_t           app_id;
1791    uint8_t          *p_buf;
1792    tBTA_HH_LE_RPT  *p_rpt;
1793
1794    if (p_dev_cb == NULL)
1795    {
1796        APPL_TRACE_ERROR("notification received from Unknown device");
1797        return;
1798    }
1799
1800    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
1801                                                                          p_data->handle);
1802
1803    app_id= p_dev_cb->app_id;
1804
1805    p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1806                                        p_dev_cb->hid_srvc.srvc_inst_id,
1807                                        p_char->uuid.uu.uuid16,
1808                                        p_char->handle);
1809    if (p_rpt == NULL)
1810    {
1811        APPL_TRACE_ERROR("notification received for Unknown Report");
1812        return;
1813    }
1814
1815    if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
1816        app_id = BTA_HH_APP_ID_MI;
1817    else if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
1818        app_id = BTA_HH_APP_ID_KB;
1819
1820    APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
1821
1822    /* need to append report ID to the head of data */
1823    if (p_rpt->rpt_id != 0)
1824    {
1825        p_buf = (uint8_t *)osi_malloc(p_data->len + 1);
1826
1827        p_buf[0] = p_rpt->rpt_id;
1828        memcpy(&p_buf[1], p_data->value, p_data->len);
1829        ++p_data->len;
1830    } else {
1831        p_buf = p_data->value;
1832    }
1833
1834    bta_hh_co_data((uint8_t)p_dev_cb->hid_handle,
1835                    p_buf,
1836                    p_data->len,
1837                    p_dev_cb->mode,
1838                    0 , /* no sub class*/
1839                    p_dev_cb->dscp_info.ctry_code,
1840                    p_dev_cb->addr,
1841                    app_id);
1842
1843    if (p_buf != p_data->value)
1844        osi_free(p_buf);
1845}
1846
1847/*******************************************************************************
1848**
1849** Function         bta_hh_gatt_open_fail
1850**
1851** Description      action function to process the open fail
1852**
1853** Returns          void
1854**
1855*******************************************************************************/
1856void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
1857{
1858    tBTA_HH_CONN            conn_dat ;
1859
1860    /* open failure in the middle of service discovery, clear all services */
1861    if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS)
1862    {
1863        bta_hh_clear_service_cache(p_cb);
1864    }
1865
1866    p_cb->disc_active = BTA_HH_LE_DISC_NONE;
1867    /* Failure in opening connection or GATT discovery failure */
1868    conn_dat.handle = p_cb->hid_handle;
1869    memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
1870    conn_dat.le_hid = true;
1871    conn_dat.scps_supported = p_cb->scps_supported;
1872
1873    if (p_cb->status == BTA_HH_OK)
1874        conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
1875    else
1876        conn_dat.status = p_cb->status;
1877
1878    /* Report OPEN fail event */
1879    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
1880
1881}
1882
1883/*******************************************************************************
1884**
1885** Function         bta_hh_gatt_close
1886**
1887** Description      action function to process the GATT close int he state machine.
1888**
1889** Returns          void
1890**
1891*******************************************************************************/
1892void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
1893{
1894    tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
1895
1896    /* deregister all notification */
1897    bta_hh_le_deregister_input_notif(p_cb);
1898    /* finaliza device driver */
1899    bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
1900    /* update total conn number */
1901    bta_hh_cb.cnt_num --;
1902
1903    disc_dat.handle = p_cb->hid_handle;
1904    disc_dat.status = p_cb->status;
1905
1906    (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
1907
1908    /* if no connection is active and HH disable is signaled, disable service */
1909    if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
1910    {
1911        bta_hh_disc_cmpl();
1912    }
1913    else
1914    {
1915#if (BTA_HH_LE_RECONN == TRUE)
1916    if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
1917    {
1918        bta_hh_le_add_dev_bg_conn(p_cb, false);
1919    }
1920#endif
1921    }
1922
1923    return;
1924
1925}
1926
1927/*******************************************************************************
1928**
1929** Function         bta_hh_le_api_disc_act
1930**
1931** Description      initaite a Close API to a remote HID device
1932**
1933** Returns          void
1934**
1935*******************************************************************************/
1936void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
1937{
1938    if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
1939    {
1940        gatt_op_queue_clean(p_cb->conn_id);
1941        BTA_GATTC_Close(p_cb->conn_id);
1942        /* remove device from background connection if intended to disconnect,
1943           do not allow reconnection */
1944        bta_hh_le_remove_dev_bg_conn(p_cb);
1945    }
1946}
1947
1948
1949/*******************************************************************************
1950**
1951** Function         read_report_cb
1952**
1953** Description      Process the Read report complete, send GET_REPORT_EVT to application
1954**                  with the report data.
1955**
1956** Parameters:
1957**
1958*******************************************************************************/
1959static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1960                           uint16_t len, uint8_t *value, void* data) {
1961    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(conn_id, handle);
1962
1963    if (p_char == NULL)
1964        return;
1965
1966    uint16_t char_uuid = p_char->uuid.uu.uuid16;
1967
1968    if (char_uuid != GATT_UUID_HID_REPORT &&
1969        char_uuid != GATT_UUID_HID_BT_KB_INPUT &&
1970        char_uuid != GATT_UUID_HID_BT_KB_OUTPUT &&
1971        char_uuid != GATT_UUID_HID_BT_MOUSE_INPUT &&
1972        char_uuid != GATT_UUID_BATTERY_LEVEL) {
1973        APPL_TRACE_ERROR("%s: Unexpected Read UUID: 0x%04x", __func__, char_uuid);
1974        return;
1975    }
1976
1977    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
1978    if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
1979    {
1980        APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
1981        return;
1982    }
1983
1984    /* GET_REPORT */
1985    BT_HDR              *p_buf = NULL;
1986    tBTA_HH_LE_RPT      *p_rpt;
1987    tBTA_HH_HSDATA      hs_data;
1988    uint8_t               *pp ;
1989
1990    memset(&hs_data, 0, sizeof(hs_data));
1991    hs_data.status  = BTA_HH_ERR;
1992    hs_data.handle  = p_dev_cb->hid_handle;
1993
1994    if (status == BTA_GATT_OK)
1995    {
1996        p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1997                                            p_char->service->handle,
1998                                            p_char->uuid.uu.uuid16,
1999                                            p_char->handle);
2000
2001        if (p_rpt != NULL && len) {
2002            p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + len + 1);
2003            /* pack data send to app */
2004            hs_data.status  = BTA_HH_OK;
2005            p_buf->len = len + 1;
2006            p_buf->layer_specific = 0;
2007            p_buf->offset = 0;
2008
2009            /* attach report ID as the first byte of the report before sending it to USB HID driver */
2010            pp = (uint8_t*)(p_buf + 1);
2011            UINT8_TO_STREAM(pp, p_rpt->rpt_id);
2012            memcpy(pp, value, len);
2013
2014            hs_data.rsp_data.p_rpt_data =p_buf;
2015        }
2016    }
2017
2018    p_dev_cb->w4_evt = 0;
2019    (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
2020
2021    osi_free_and_reset((void **)&p_buf);
2022}
2023
2024/*******************************************************************************
2025**
2026** Function         bta_hh_le_get_rpt
2027**
2028** Description      GET_REPORT on a LE HID Report
2029**
2030** Returns          void
2031**
2032*******************************************************************************/
2033void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, tBTA_HH_RPT_TYPE r_type, uint8_t rpt_id)
2034{
2035    tBTA_HH_LE_RPT  *p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report,
2036                                                          p_cb->mode, r_type, rpt_id);
2037
2038    if (p_rpt == NULL) {
2039        APPL_TRACE_ERROR("%s: no matching report", __func__);
2040        return;
2041    }
2042
2043    p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
2044    gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_rpt->char_inst_id, read_report_cb, p_cb);
2045}
2046
2047static void write_report_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data)
2048{
2049    tBTA_HH_CBDATA cback_data;
2050    tBTA_HH_DEV_CB *p_dev_cb = (tBTA_HH_DEV_CB*)data;
2051    uint16_t cb_evt = p_dev_cb->w4_evt;
2052
2053    if (cb_evt == 0)
2054        return;
2055
2056#if (BTA_HH_DEBUG == TRUE)
2057    APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
2058#endif
2059
2060    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(conn_id, handle);
2061    uint16_t uuid = p_char->uuid.uu.uuid16;
2062    if (uuid != GATT_UUID_HID_REPORT &&
2063        uuid != GATT_UUID_HID_BT_KB_INPUT &&
2064        uuid != GATT_UUID_HID_BT_MOUSE_INPUT &&
2065        uuid != GATT_UUID_HID_BT_KB_OUTPUT) {
2066        return;
2067    }
2068
2069    /* Set Report finished */
2070    cback_data.handle  = p_dev_cb->hid_handle;
2071    cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
2072    p_dev_cb->w4_evt = 0;
2073    (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2074}
2075/*******************************************************************************
2076**
2077** Function         bta_hh_le_write_rpt
2078**
2079** Description      SET_REPORT/or DATA output on a LE HID Report
2080**
2081** Returns          void
2082**
2083*******************************************************************************/
2084void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb,
2085                         tBTA_HH_RPT_TYPE r_type,
2086                         BT_HDR *p_buf, uint16_t w4_evt )
2087{
2088    tBTA_HH_LE_RPT  *p_rpt;
2089    uint8_t rpt_id;
2090
2091    if (p_buf == NULL || p_buf->len == 0)
2092    {
2093        APPL_TRACE_ERROR("%s: Illegal data", __func__);
2094        return;
2095    }
2096
2097    /* strip report ID from the data */
2098    uint8_t *vec_start = (uint8_t *)(p_buf + 1) + p_buf->offset;
2099    STREAM_TO_UINT8(rpt_id, vec_start);
2100    vector<uint8_t> value(vec_start, vec_start + p_buf->len - 1);
2101
2102    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
2103    if (p_rpt == NULL) {
2104        APPL_TRACE_ERROR("%s: no matching report", __func__);
2105        osi_free(p_buf);
2106        return;
2107    }
2108
2109    p_cb->w4_evt = w4_evt;
2110
2111    const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_cb->conn_id,
2112                                                                          p_rpt->char_inst_id);
2113
2114    tBTA_GATTC_WRITE_TYPE write_type = BTA_GATTC_TYPE_WRITE;
2115    if (p_char && (p_char->properties & BTA_GATT_CHAR_PROP_BIT_WRITE_NR))
2116        write_type = BTA_GATTC_TYPE_WRITE_NO_RSP;
2117
2118    gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
2119                        std::move(value), write_type, write_report_cb, p_cb);
2120}
2121
2122/*******************************************************************************
2123**
2124** Function         bta_hh_le_suspend
2125**
2126** Description      send LE suspend or exit suspend mode to remote device.
2127**
2128** Returns          void
2129**
2130*******************************************************************************/
2131void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
2132{
2133    ctrl_type -= BTA_HH_CTRL_SUSPEND;
2134
2135    //We don't care about response
2136    gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.control_point_handle,
2137                        {(uint8_t) ctrl_type}, BTA_GATTC_TYPE_WRITE_NO_RSP, NULL, NULL);
2138}
2139
2140/*******************************************************************************
2141**
2142** Function         bta_hh_le_write_dev_act
2143**
2144** Description      Write LE device action. can be SET/GET/DATA transaction.
2145**
2146** Returns          void
2147**
2148*******************************************************************************/
2149void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2150{
2151    switch(p_data->api_sndcmd.t_type)
2152    {
2153        case HID_TRANS_SET_PROTOCOL:
2154            p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
2155            bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
2156            break;
2157
2158        case HID_TRANS_GET_PROTOCOL:
2159            bta_hh_le_get_protocol_mode(p_cb);
2160            break;
2161
2162        case HID_TRANS_GET_REPORT:
2163            bta_hh_le_get_rpt(p_cb,
2164                              p_data->api_sndcmd.param,
2165                              p_data->api_sndcmd.rpt_id);
2166            break;
2167
2168        case HID_TRANS_SET_REPORT:
2169            bta_hh_le_write_rpt(p_cb,
2170                                p_data->api_sndcmd.param,
2171                                p_data->api_sndcmd.p_data,
2172                                BTA_HH_SET_RPT_EVT);
2173            break;
2174
2175        case HID_TRANS_DATA:  /* output report */
2176
2177            bta_hh_le_write_rpt(p_cb,
2178                                p_data->api_sndcmd.param,
2179                                p_data->api_sndcmd.p_data,
2180                                BTA_HH_DATA_EVT);
2181            break;
2182
2183        case HID_TRANS_CONTROL:
2184            /* no handshake event will be generated */
2185            /* if VC_UNPLUG is issued, set flag */
2186            if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
2187                p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
2188            {
2189                bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
2190            }
2191            break;
2192
2193        default:
2194            APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
2195                __func__, p_data->api_sndcmd.t_type);
2196            break;
2197    }
2198}
2199
2200/*******************************************************************************
2201**
2202** Function         bta_hh_le_get_dscp_act
2203**
2204** Description      Send ReportDescriptor to application for all HID services.
2205**
2206** Returns          void
2207**
2208*******************************************************************************/
2209void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
2210{
2211    if (p_cb->hid_srvc.in_use)
2212    {
2213        p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len;
2214        p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list;
2215
2216        (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
2217    }
2218}
2219
2220/*******************************************************************************
2221**
2222** Function         bta_hh_le_add_dev_bg_conn
2223**
2224** Description      Remove a LE HID device from back ground connection procedure.
2225**
2226** Returns          void
2227**
2228*******************************************************************************/
2229static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, bool check_bond)
2230{
2231    uint8_t           sec_flag=0;
2232    bool         to_add = true;
2233
2234    if (check_bond)
2235    {
2236        /* start reconnection if remote is a bonded device */
2237        /* verify bond */
2238        BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
2239
2240        if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
2241            to_add = false;
2242    }
2243
2244    if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
2245        !p_cb->in_bg_conn && to_add)
2246    {
2247        /* add device into BG connection to accept remote initiated connection */
2248        BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, false, BTA_GATT_TRANSPORT_LE);
2249        p_cb->in_bg_conn = true;
2250
2251        BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
2252    }
2253    return;
2254}
2255
2256/*******************************************************************************
2257**
2258** Function         bta_hh_le_add_device
2259**
2260** Description      Add a LE HID device as a known device, and also add the address
2261**                  into back ground connection WL for incoming connection.
2262**
2263** Returns          void
2264**
2265*******************************************************************************/
2266uint8_t bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
2267{
2268    p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
2269    bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
2270
2271    /* update DI information */
2272    bta_hh_update_di_info(p_cb,
2273                          p_dev_info->dscp_info.vendor_id,
2274                          p_dev_info->dscp_info.product_id,
2275                          p_dev_info->dscp_info.version,
2276                          p_dev_info->dscp_info.flag);
2277
2278    /* add to BTA device list */
2279    bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
2280                              p_dev_info->attr_mask,
2281                              &p_dev_info->dscp_info.descriptor,
2282                              p_dev_info->sub_class,
2283                              p_dev_info->dscp_info.ssr_max_latency,
2284                              p_dev_info->dscp_info.ssr_min_tout,
2285                              p_dev_info->app_id);
2286
2287    bta_hh_le_add_dev_bg_conn(p_cb, false);
2288
2289    return p_cb->hid_handle;
2290}
2291
2292/*******************************************************************************
2293**
2294** Function         bta_hh_le_remove_dev_bg_conn
2295**
2296** Description      Remove a LE HID device from back ground connection procedure.
2297**
2298** Returns          void
2299**
2300*******************************************************************************/
2301void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
2302{
2303    if (p_dev_cb->in_bg_conn)
2304    {
2305        p_dev_cb->in_bg_conn = false;
2306
2307        BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, false);
2308    }
2309
2310    /* deregister all notifications */
2311    bta_hh_le_deregister_input_notif(p_dev_cb);
2312}
2313
2314/*******************************************************************************
2315**
2316** Function         bta_hh_gattc_callback
2317**
2318** Description      This is GATT client callback function used in BTA HH.
2319**
2320** Parameters:
2321**
2322*******************************************************************************/
2323static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
2324{
2325    tBTA_HH_DEV_CB *p_dev_cb;
2326#if (BTA_HH_DEBUG == TRUE)
2327    APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
2328#endif
2329    if (p_data == NULL)
2330        return;
2331
2332    switch (event)
2333    {
2334        case BTA_GATTC_REG_EVT: /* 0 */
2335            bta_hh_le_register_cmpl(&p_data->reg_oper);
2336            break;
2337
2338        case BTA_GATTC_DEREG_EVT: /* 1 */
2339            bta_hh_cleanup_disable(p_data->reg_oper.status);
2340            break;
2341
2342        case BTA_GATTC_OPEN_EVT: /* 2 */
2343            p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
2344            if (p_dev_cb) {
2345                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
2346            }
2347            break;
2348
2349        case BTA_GATTC_CLOSE_EVT: /* 5 */
2350            bta_hh_le_close(&p_data->close);
2351            break;
2352
2353        case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
2354            bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
2355            break;
2356
2357        case BTA_GATTC_NOTIF_EVT: /* 10 */
2358            bta_hh_le_input_rpt_notify(&p_data->notify);
2359            break;
2360
2361        case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
2362            p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
2363            if (p_dev_cb) {
2364                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
2365                              (tBTA_HH_DATA *)&p_data->enc_cmpl);
2366            }
2367            break;
2368
2369        default:
2370            break;
2371    }
2372}
2373
2374static void read_report_descriptor_ccc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
2375                                          uint16_t len, uint8_t *value, void* data)
2376{
2377    tBTA_HH_LE_RPT  *p_rpt = (tBTA_HH_LE_RPT*)data;
2378    uint8_t   *pp = value;
2379    STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
2380
2381    APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
2382}
2383
2384/*******************************************************************************
2385**
2386** Function         bta_hh_le_hid_read_rpt_clt_cfg
2387**
2388** Description      a test command to read report descriptor client configuration
2389**
2390** Returns          void
2391**
2392*******************************************************************************/
2393void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, uint8_t rpt_id)
2394{
2395    tBTA_HH_DEV_CB *p_cb = NULL;
2396    tBTA_HH_LE_RPT *p_rpt ;
2397    uint8_t           index = BTA_HH_IDX_INVALID;
2398
2399    index = bta_hh_find_cb(bd_addr);
2400    if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
2401    {
2402        APPL_TRACE_ERROR("%s: unknown device", __func__);
2403        return;
2404    }
2405
2406    p_cb = &bta_hh_cb.kdev[index];
2407
2408    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, BTA_HH_RPTT_INPUT,
2409                                         rpt_id);
2410
2411    if (p_rpt == NULL)
2412    {
2413        APPL_TRACE_ERROR("%s: no matching report", __func__);
2414        return;
2415    }
2416
2417    bta_hh_le_read_char_descriptor(p_cb, p_rpt->char_inst_id, GATT_UUID_CHAR_CLIENT_CONFIG,
2418                               read_report_descriptor_ccc_cb, p_rpt);
2419    return;
2420}
2421
2422/*******************************************************************************
2423**
2424** Function         bta_hh_process_cache_rpt
2425**
2426** Description      Process the cached reports
2427**
2428** Parameters:
2429**
2430*******************************************************************************/
2431//TODO(jpawlowski): uncomment when fixed
2432// static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
2433//                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
2434//                                       uint8_t num_rpt)
2435// {
2436//     uint8_t                       i = 0;
2437//     tBTA_HH_LE_RPT              *p_rpt;
2438
2439//     if (num_rpt != 0)  /* no cache is found */
2440//     {
2441//         p_cb->hid_srvc.in_use = true;
2442
2443//         /* set the descriptor info */
2444//         p_cb->hid_srvc.descriptor.dl_len =
2445//                 p_cb->dscp_info.descriptor.dl_len;
2446//         p_cb->hid_srvc.descriptor.dsc_list =
2447//                     p_cb->dscp_info.descriptor.dsc_list;
2448
2449//         for (; i <num_rpt; i ++, p_rpt_cache ++)
2450//         {
2451//             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
2452//                                                p_rpt_cache->srvc_inst_id,
2453//                                                p_rpt_cache->rpt_uuid,
2454//                                                p_rpt_cache->char_inst_id,
2455//                                                p_rpt_cache->prop))  == NULL)
2456//             {
2457//                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
2458//                 break;
2459//             }
2460//             else
2461//             {
2462//                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
2463//                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
2464
2465//                 if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
2466//                     p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
2467//                     (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
2468//                 {
2469//                     p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
2470//                 }
2471//             }
2472//         }
2473//     }
2474// }
2475
2476#endif
2477
2478
2479
2480
2481