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