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