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