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