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