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