1 /******************************************************************************
2 *
3 * Copyright 2009-2012 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 #include "bta_hh_co.h"
20
21 #include <com_android_bluetooth_flags.h>
22 #include <fcntl.h>
23 #include <linux/uhid.h>
24 #include <poll.h>
25 #include <pthread.h>
26 #include <stdint.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include <cerrno>
31
32 #include "bta_hh_api.h"
33 #include "btif_hh.h"
34 #include "hci/controller_interface.h"
35 #include "main/shim/entry.h"
36 #include "osi/include/allocator.h"
37 #include "osi/include/compat.h"
38 #include "osi/include/osi.h"
39 #include "storage/config_keys.h"
40 #include "types/raw_address.h"
41
42 const char* dev_path = "/dev/uhid";
43
44 #include "btif_config.h"
45 #define BTA_HH_NV_LOAD_MAX 16
46 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
47 #define BTA_HH_CACHE_REPORT_VERSION 1
48 #define THREAD_NORMAL_PRIORITY 0
49 #define BT_HH_THREAD_PREFIX "bt_hh_"
50 #define BTA_HH_UHID_POLL_PERIOD_MS 50
51 /* Max number of polling interrupt allowed */
52 #define BTA_HH_UHID_INTERRUPT_COUNT_MAX 100
53
54 using namespace bluetooth;
55
56 static const bthh_report_type_t map_rtype_uhid_hh[] = {
57 BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, BTHH_INPUT_REPORT};
58
59 static void* btif_hh_poll_event_thread(void* arg);
60
uhid_set_non_blocking(int fd)61 void uhid_set_non_blocking(int fd) {
62 int opts = fcntl(fd, F_GETFL);
63 if (opts < 0) log::error("Getting flags failed ({})", strerror(errno));
64
65 opts |= O_NONBLOCK;
66
67 if (fcntl(fd, F_SETFL, opts) < 0)
68 log::verbose("Setting non-blocking flag failed ({})", strerror(errno));
69 }
70
uhid_feature_req_handler(btif_hh_uhid_t * p_uhid,struct uhid_feature_req & req)71 static bool uhid_feature_req_handler(btif_hh_uhid_t* p_uhid,
72 struct uhid_feature_req& req) {
73 log::debug("Report type = {}, id = {}", req.rtype, req.rnum);
74
75 if (req.rtype > UHID_INPUT_REPORT) {
76 log::error("Invalid report type {}", req.rtype);
77 return false;
78 }
79
80 if (p_uhid->get_rpt_id_queue == nullptr) {
81 log::error("Queue is not initialized");
82 return false;
83 }
84
85 uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t));
86 *context = req.id;
87
88 if (!fixed_queue_try_enqueue(p_uhid->get_rpt_id_queue, (void*)context)) {
89 osi_free(context);
90 log::error("Queue is full, dropping event {}", req.id);
91 return false;
92 }
93
94 btif_hh_getreport(p_uhid, map_rtype_uhid_hh[req.rtype], req.rnum, 0);
95 return true;
96 }
97
98 #if ENABLE_UHID_SET_REPORT
uhid_set_report_req_handler(btif_hh_uhid_t * p_uhid,struct uhid_set_report_req & req)99 static bool uhid_set_report_req_handler(btif_hh_uhid_t* p_uhid,
100 struct uhid_set_report_req& req) {
101 log::debug("Report type = {}, id = {}", req.rtype, req.rnum);
102
103 if (req.rtype > UHID_INPUT_REPORT) {
104 log::error("Invalid report type {}", req.rtype);
105 return false;
106 }
107
108 if (p_uhid->set_rpt_id_queue == nullptr) {
109 log::error("Queue is not initialized");
110 return false;
111 }
112
113 uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t));
114 *context = req.id;
115
116 if (!fixed_queue_try_enqueue(p_uhid->set_rpt_id_queue, (void*)context)) {
117 osi_free(context);
118 log::error("Queue is full, dropping event {}", req.id);
119 return false;
120 }
121
122 btif_hh_setreport(p_uhid, map_rtype_uhid_hh[req.rtype], req.size, req.data);
123 return true;
124 }
125 #endif // ENABLE_UHID_SET_REPORT
126
127 /*Internal function to perform UHID write and error checking*/
uhid_write(int fd,const struct uhid_event * ev)128 static int uhid_write(int fd, const struct uhid_event* ev) {
129 ssize_t ret;
130 OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev)));
131
132 if (ret < 0) {
133 int rtn = -errno;
134 log::error("Cannot write to uhid:{}", strerror(errno));
135 return rtn;
136 } else if (ret != (ssize_t)sizeof(*ev)) {
137 log::error("Wrong size written to uhid: {} != {}", ret, sizeof(*ev));
138 return -EFAULT;
139 }
140
141 return 0;
142 }
143
144 /* Internal function to parse the events received from UHID driver*/
uhid_read_event(btif_hh_uhid_t * p_uhid)145 static int uhid_read_event(btif_hh_uhid_t* p_uhid) {
146 log::assert_that(p_uhid != nullptr, "assert failed: p_uhid != nullptr");
147
148 struct uhid_event ev;
149 memset(&ev, 0, sizeof(ev));
150
151 ssize_t ret;
152 OSI_NO_INTR(ret = read(p_uhid->fd, &ev, sizeof(ev)));
153
154 if (ret == 0) {
155 log::error("Read HUP on uhid-cdev {}", strerror(errno));
156 return -EFAULT;
157 } else if (ret < 0) {
158 log::error("Cannot read uhid-cdev: {}", strerror(errno));
159 return -errno;
160 }
161
162 switch (ev.type) {
163 case UHID_START:
164 log::verbose("UHID_START from uhid-dev\n");
165 p_uhid->ready_for_data = true;
166 break;
167 case UHID_STOP:
168 log::verbose("UHID_STOP from uhid-dev\n");
169 p_uhid->ready_for_data = false;
170 break;
171 case UHID_OPEN:
172 log::verbose("UHID_OPEN from uhid-dev\n");
173 p_uhid->ready_for_data = true;
174 break;
175 case UHID_CLOSE:
176 log::verbose("UHID_CLOSE from uhid-dev\n");
177 p_uhid->ready_for_data = false;
178 break;
179 case UHID_OUTPUT:
180 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) {
181 log::error("Invalid size read from uhid-dev: {} < {}", ret,
182 sizeof(ev.type) + sizeof(ev.u.output));
183 return -EFAULT;
184 }
185
186 log::verbose("UHID_OUTPUT: Report type = {}, report_size = {}",
187 ev.u.output.rtype, ev.u.output.size);
188 // Send SET_REPORT with feature report if the report type in output event
189 // is FEATURE
190 if (ev.u.output.rtype == UHID_FEATURE_REPORT)
191 btif_hh_setreport(p_uhid, BTHH_FEATURE_REPORT, ev.u.output.size,
192 ev.u.output.data);
193 else if (ev.u.output.rtype == UHID_OUTPUT_REPORT)
194 btif_hh_senddata(p_uhid, ev.u.output.size, ev.u.output.data);
195 else
196 log::error("UHID_OUTPUT: Invalid report type = {}", ev.u.output.rtype);
197 break;
198 case UHID_OUTPUT_EV:
199 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output_ev))) {
200 log::error("Invalid size read from uhid-dev: {} < {}", ret,
201 sizeof(ev.type) + sizeof(ev.u.output_ev));
202 return -EFAULT;
203 }
204 log::verbose("UHID_OUTPUT_EV from uhid-dev\n");
205 break;
206
207 case UHID_FEATURE: // UHID_GET_REPORT
208 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.feature))) {
209 log::error("UHID_GET_REPORT: Invalid size read from uhid-dev: {} < {}",
210 ret, sizeof(ev.type) + sizeof(ev.u.feature));
211 return -EFAULT;
212 }
213
214 if (!uhid_feature_req_handler(p_uhid, ev.u.feature)) {
215 return -EFAULT;
216 }
217
218 break;
219
220 #if ENABLE_UHID_SET_REPORT
221 case UHID_SET_REPORT: {
222 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.set_report))) {
223 log::error("UHID_SET_REPORT: Invalid size read from uhid-dev: {} < {}",
224 ret, sizeof(ev.type) + sizeof(ev.u.set_report));
225 return -EFAULT;
226 }
227
228 if (!uhid_set_report_req_handler(p_uhid, ev.u.set_report)) {
229 return -EFAULT;
230 }
231 break;
232 }
233 #endif // ENABLE_UHID_SET_REPORT
234
235 default:
236 log::error("Invalid event from uhid-dev: {}\n", ev.type);
237 }
238
239 return 0;
240 }
241
242 /*******************************************************************************
243 *
244 * Function create_thread
245 *
246 * Description creat a select loop
247 *
248 * Returns pthread_t
249 *
250 ******************************************************************************/
create_thread(void * (* start_routine)(void *),void * arg)251 static inline pthread_t create_thread(void* (*start_routine)(void*),
252 void* arg) {
253 log::verbose("create_thread: entered");
254 pthread_attr_t thread_attr;
255
256 pthread_attr_init(&thread_attr);
257 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
258 pthread_t thread_id = -1;
259 if (pthread_create(&thread_id, &thread_attr, start_routine, arg) != 0) {
260 log::error("pthread_create : {}", strerror(errno));
261 return -1;
262 }
263 log::verbose("create_thread: thread created successfully");
264 return thread_id;
265 }
266
267 /* Internal function to close the UHID driver*/
uhid_fd_close(btif_hh_uhid_t * p_uhid)268 static void uhid_fd_close(btif_hh_uhid_t* p_uhid) {
269 if (p_uhid->fd >= 0) {
270 struct uhid_event ev = {};
271 ev.type = UHID_DESTROY;
272 uhid_write(p_uhid->fd, &ev);
273 log::debug("Closing fd={}, addr:{}", p_uhid->fd, p_uhid->link_spec);
274 close(p_uhid->fd);
275 p_uhid->fd = -1;
276 }
277 }
278
279 /* Internal function to open the UHID driver*/
uhid_fd_open(btif_hh_device_t * p_dev)280 static bool uhid_fd_open(btif_hh_device_t* p_dev) {
281 if (p_dev->uhid.fd < 0) {
282 p_dev->uhid.fd = open(dev_path, O_RDWR | O_CLOEXEC);
283 if (p_dev->uhid.fd < 0) {
284 log::error("Failed to open uhid, err:{}", strerror(errno));
285 return false;
286 }
287 }
288
289 if (p_dev->uhid.hh_keep_polling == 0) {
290 p_dev->uhid.hh_keep_polling = 1;
291 p_dev->hh_poll_thread_id =
292 create_thread(btif_hh_poll_event_thread, &p_dev->uhid);
293 }
294 return true;
295 }
296
uhid_fd_poll(btif_hh_uhid_t * p_uhid,std::array<struct pollfd,1> & pfds)297 static int uhid_fd_poll(btif_hh_uhid_t* p_uhid,
298 std::array<struct pollfd, 1>& pfds) {
299 int ret = 0;
300 int counter = 0;
301
302 do {
303 if (com::android::bluetooth::flags::break_uhid_polling_early() &&
304 !p_uhid->hh_keep_polling) {
305 log::debug("Polling stopped");
306 return -1;
307 }
308
309 if (counter++ > BTA_HH_UHID_INTERRUPT_COUNT_MAX) {
310 log::error("Polling interrupted consecutively {} times",
311 BTA_HH_UHID_INTERRUPT_COUNT_MAX);
312 return -1;
313 }
314
315 ret = poll(pfds.data(), pfds.size(), BTA_HH_UHID_POLL_PERIOD_MS);
316 } while (ret == -1 && errno == EINTR);
317
318 if (!com::android::bluetooth::flags::break_uhid_polling_early()) {
319 if (ret == 0) {
320 log::verbose("Polling timed out, attempt to read (old behavior)");
321 return 1;
322 }
323 }
324
325 return ret;
326 }
327
uhid_start_polling(btif_hh_uhid_t * p_uhid)328 static void uhid_start_polling(btif_hh_uhid_t* p_uhid) {
329 std::array<struct pollfd, 1> pfds = {};
330 pfds[0].fd = p_uhid->fd;
331 pfds[0].events = POLLIN;
332
333 while (p_uhid->hh_keep_polling) {
334 int ret = uhid_fd_poll(p_uhid, pfds);
335
336 if (ret < 0) {
337 log::error("Cannot poll for fds: {}\n", strerror(errno));
338 break;
339 } else if (ret == 0) {
340 /* Poll timeout, poll again */
341 continue;
342 }
343
344 /* At least one of the fd is ready */
345 if (pfds[0].revents & POLLIN) {
346 log::verbose("POLLIN");
347 int result = uhid_read_event(p_uhid);
348 if (result != 0) {
349 log::error("Unhandled UHID event, error: {}", result);
350 break;
351 }
352 }
353 }
354 }
355
uhid_configure_thread(btif_hh_uhid_t * p_uhid)356 static bool uhid_configure_thread(btif_hh_uhid_t* p_uhid) {
357 pid_t pid = gettid();
358 // This thread is created by bt_main_thread with RT priority. Lower the thread
359 // priority here since the tasks in this thread is not timing critical.
360 struct sched_param sched_params;
361 sched_params.sched_priority = THREAD_NORMAL_PRIORITY;
362 if (sched_setscheduler(pid, SCHED_OTHER, &sched_params)) {
363 log::error("Failed to set thread priority to normal: {}", strerror(errno));
364 return false;
365 }
366
367 // Change the name of thread
368 char thread_name[16] = {};
369 sprintf(thread_name, BT_HH_THREAD_PREFIX "%02x:%02x",
370 p_uhid->link_spec.addrt.bda.address[4],
371 p_uhid->link_spec.addrt.bda.address[5]);
372 pthread_setname_np(pthread_self(), thread_name);
373 log::debug("Host hid polling thread created name:{} pid:{} fd:{}",
374 thread_name, pid, p_uhid->fd);
375
376 // Set the uhid fd as non-blocking to ensure we never block the BTU thread
377 uhid_set_non_blocking(p_uhid->fd);
378
379 return true;
380 }
381
382 /*******************************************************************************
383 *
384 * Function btif_hh_poll_event_thread
385 *
386 * Description the polling thread which polls for event from UHID driver
387 *
388 * Returns void
389 *
390 ******************************************************************************/
btif_hh_poll_event_thread(void * arg)391 static void* btif_hh_poll_event_thread(void* arg) {
392 btif_hh_uhid_t* p_uhid = (btif_hh_uhid_t*)arg;
393
394 if (uhid_configure_thread(p_uhid)) {
395 uhid_start_polling(p_uhid);
396 }
397
398 /* Todo: Disconnect if loop exited due to a failure */
399 log::info("Polling thread stopped for device {}", p_uhid->link_spec);
400 p_uhid->hh_keep_polling = 0;
401 uhid_fd_close(p_uhid);
402 return 0;
403 }
404
bta_hh_co_write(int fd,uint8_t * rpt,uint16_t len)405 int bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len) {
406 log::verbose("UHID write {}", len);
407
408 struct uhid_event ev;
409 memset(&ev, 0, sizeof(ev));
410 ev.type = UHID_INPUT;
411 ev.u.input.size = len;
412 if (len > sizeof(ev.u.input.data)) {
413 log::warn("Report size greater than allowed size");
414 return -1;
415 }
416 memcpy(ev.u.input.data, rpt, len);
417
418 return uhid_write(fd, &ev);
419 }
420
421 /*******************************************************************************
422 *
423 * Function bta_hh_co_open
424 *
425 * Description When connection is opened, this call-out function is executed
426 * by HH to do platform specific initialization.
427 *
428 * Returns True if platform specific initialization is successful
429 ******************************************************************************/
bta_hh_co_open(uint8_t dev_handle,uint8_t sub_class,tBTA_HH_ATTR_MASK attr_mask,uint8_t app_id,tAclLinkSpec & link_spec)430 bool bta_hh_co_open(uint8_t dev_handle, uint8_t sub_class,
431 tBTA_HH_ATTR_MASK attr_mask, uint8_t app_id,
432 tAclLinkSpec& link_spec) {
433 bool new_device = false;
434
435 if (dev_handle == BTA_HH_INVALID_HANDLE) {
436 log::warn("dev_handle ({}) is invalid", dev_handle);
437 return false;
438 }
439
440 // Reuse existing instance if possible
441 btif_hh_device_t* p_dev = btif_hh_find_dev_by_handle(dev_handle);
442 if (p_dev != nullptr) {
443 log::info(
444 "Found an existing device with the same handle dev_status={}, "
445 "device={}, attr_mask=0x{:04x}, sub_class=0x{:02x}, app_id={}, "
446 "dev_handle={}",
447 p_dev->dev_status, p_dev->link_spec, p_dev->attr_mask, p_dev->sub_class,
448 p_dev->app_id, dev_handle);
449 } else { // Use an empty slot
450 p_dev = btif_hh_find_empty_dev();
451 if (p_dev == nullptr) {
452 log::error("Too many HID devices are connected");
453 return false;
454 }
455
456 new_device = true;
457 log::verbose("New HID device added for handle {}", dev_handle);
458
459 p_dev->uhid.fd = -1;
460 p_dev->uhid.hh_keep_polling = 0;
461 p_dev->uhid.link_spec = link_spec;
462 p_dev->uhid.dev_handle = dev_handle;
463 p_dev->attr_mask = attr_mask;
464 p_dev->sub_class = sub_class;
465 p_dev->app_id = app_id;
466 p_dev->local_vup = false;
467 }
468
469 if (!uhid_fd_open(p_dev)) {
470 return false;
471 }
472
473 if (new_device) {
474 btif_hh_cb.device_num++;
475 }
476
477 p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
478 p_dev->dev_handle = dev_handle;
479 p_dev->uhid.get_rpt_id_queue = fixed_queue_new(SIZE_MAX);
480 log::assert_that(p_dev->uhid.get_rpt_id_queue,
481 "assert failed: p_dev->uhid.get_rpt_id_queue");
482 #if ENABLE_UHID_SET_REPORT
483 p_dev->uhid.set_rpt_id_queue = fixed_queue_new(SIZE_MAX);
484 log::assert_that(p_dev->uhid.set_rpt_id_queue,
485 "assert failed: p_dev->uhid.set_rpt_id_queue");
486 #endif // ENABLE_UHID_SET_REPORT
487
488 log::debug("Return device status {}", p_dev->dev_status);
489 return true;
490 }
491
492 /*******************************************************************************
493 *
494 * Function bta_hh_co_close
495 *
496 * Description When connection is closed, this call-out function is executed
497 * by HH to do platform specific finalization.
498 *
499 * Parameters p_dev - device
500 *
501 * Returns void.
502 ******************************************************************************/
bta_hh_co_close(btif_hh_device_t * p_dev)503 void bta_hh_co_close(btif_hh_device_t* p_dev) {
504 log::info("Closing device handle={}, status={}, address={}",
505 p_dev->dev_handle, p_dev->dev_status, p_dev->link_spec);
506
507 /* Clear the queues */
508 fixed_queue_flush(p_dev->uhid.get_rpt_id_queue, osi_free);
509 fixed_queue_free(p_dev->uhid.get_rpt_id_queue, NULL);
510 p_dev->uhid.get_rpt_id_queue = NULL;
511 #if ENABLE_UHID_SET_REPORT
512 fixed_queue_flush(p_dev->uhid.set_rpt_id_queue, osi_free);
513 fixed_queue_free(p_dev->uhid.set_rpt_id_queue, nullptr);
514 p_dev->uhid.set_rpt_id_queue = nullptr;
515 #endif // ENABLE_UHID_SET_REPORT
516
517 /* Stop the polling thread */
518 if (p_dev->uhid.hh_keep_polling) {
519 p_dev->uhid.hh_keep_polling = 0;
520 pthread_join(p_dev->hh_poll_thread_id, NULL);
521 p_dev->hh_poll_thread_id = -1;
522 }
523 /* UHID file descriptor is closed by the polling thread */
524 }
525
526 /*******************************************************************************
527 *
528 * Function bta_hh_co_data
529 *
530 * Description This function is executed by BTA when HID host receive a
531 * data report.
532 *
533 * Parameters dev_handle - device handle
534 * *p_rpt - pointer to the report data
535 * len - length of report data
536 *
537 * Returns void
538 ******************************************************************************/
bta_hh_co_data(uint8_t dev_handle,uint8_t * p_rpt,uint16_t len)539 void bta_hh_co_data(uint8_t dev_handle, uint8_t* p_rpt, uint16_t len) {
540 btif_hh_device_t* p_dev;
541
542 log::verbose("dev_handle = {}", dev_handle);
543
544 p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
545 if (p_dev == NULL) {
546 log::warn("Error: unknown HID device handle {}", dev_handle);
547 return;
548 }
549
550 // Wait a maximum of MAX_POLLING_ATTEMPTS x POLLING_SLEEP_DURATION in case
551 // device creation is pending.
552 if (p_dev->uhid.fd >= 0) {
553 uint32_t polling_attempts = 0;
554 while (!p_dev->uhid.ready_for_data &&
555 polling_attempts++ < BTIF_HH_MAX_POLLING_ATTEMPTS) {
556 usleep(BTIF_HH_POLLING_SLEEP_DURATION_US);
557 }
558 }
559
560 // Send the HID data to the kernel.
561 if ((p_dev->uhid.fd >= 0) && p_dev->uhid.ready_for_data) {
562 bta_hh_co_write(p_dev->uhid.fd, p_rpt, len);
563 } else {
564 log::warn("Error: fd = {}, ready {}, len = {}", p_dev->uhid.fd,
565 p_dev->uhid.ready_for_data, len);
566 }
567 }
568
569 /*******************************************************************************
570 *
571 * Function bta_hh_co_send_hid_info
572 *
573 * Description This function is called in btif_hh.c to process DSCP
574 * received.
575 *
576 * Parameters dev_handle - device handle
577 * dscp_len - report descriptor length
578 * *p_dscp - report descriptor
579 *
580 * Returns void
581 ******************************************************************************/
bta_hh_co_send_hid_info(btif_hh_device_t * p_dev,const char * dev_name,uint16_t vendor_id,uint16_t product_id,uint16_t version,uint8_t ctry_code,int dscp_len,uint8_t * p_dscp)582 void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name,
583 uint16_t vendor_id, uint16_t product_id,
584 uint16_t version, uint8_t ctry_code, int dscp_len,
585 uint8_t* p_dscp) {
586 int result;
587 struct uhid_event ev;
588
589 if (p_dev->uhid.fd < 0) {
590 log::warn("Error: fd = {}, dscp_len = {}", p_dev->uhid.fd, dscp_len);
591 return;
592 }
593
594 log::warn("fd = {}, name = [{}], dscp_len = {}", p_dev->uhid.fd, dev_name,
595 dscp_len);
596 log::warn(
597 "vendor_id = 0x{:04x}, product_id = 0x{:04x}, version= "
598 "0x{:04x},ctry_code=0x{:02x}",
599 vendor_id, product_id, version, ctry_code);
600
601 // Create and send hid descriptor to kernel
602 memset(&ev, 0, sizeof(ev));
603 ev.type = UHID_CREATE;
604 strlcpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name));
605 // TODO (b/258090765) fix: ToString -> ToColonSepHexString
606 snprintf((char*)ev.u.create.uniq, sizeof(ev.u.create.uniq), "%s",
607 p_dev->link_spec.addrt.bda.ToString().c_str());
608
609 // Write controller address to phys field to correlate the hid device with a
610 // specific bluetooth controller.
611 auto controller = bluetooth::shim::GetController();
612 // TODO (b/258090765) fix: ToString -> ToColonSepHexString
613 snprintf((char*)ev.u.create.phys, sizeof(ev.u.create.phys), "%s",
614 controller->GetMacAddress().ToString().c_str());
615
616 ev.u.create.rd_size = dscp_len;
617 ev.u.create.rd_data = p_dscp;
618 ev.u.create.bus = BUS_BLUETOOTH;
619 ev.u.create.vendor = vendor_id;
620 ev.u.create.product = product_id;
621 ev.u.create.version = version;
622 ev.u.create.country = ctry_code;
623 result = uhid_write(p_dev->uhid.fd, &ev);
624
625 log::warn("wrote descriptor to fd = {}, dscp_len = {}, result = {}",
626 p_dev->uhid.fd, dscp_len, result);
627
628 if (result) {
629 log::warn("Error: failed to send DSCP, result = {}", result);
630
631 /* The HID report descriptor is corrupted. Close the driver. */
632 close(p_dev->uhid.fd);
633 p_dev->uhid.fd = -1;
634 }
635 }
636
637 /*******************************************************************************
638 *
639 * Function bta_hh_co_set_rpt_rsp
640 *
641 * Description This callout function is executed by HH when Set Report
642 * Response is received on Control Channel.
643 *
644 * Returns void.
645 *
646 ******************************************************************************/
bta_hh_co_set_rpt_rsp(uint8_t dev_handle,uint8_t status)647 void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) {
648 #if ENABLE_UHID_SET_REPORT
649 log::verbose("dev_handle = {}", dev_handle);
650
651 btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
652 if (p_dev == nullptr) {
653 log::warn("Unknown HID device handle {}", dev_handle);
654 return;
655 }
656
657 if (!p_dev->uhid.set_rpt_id_queue) {
658 log::warn("Missing UHID_SET_REPORT id queue");
659 return;
660 }
661
662 // Send the HID set report reply to the kernel.
663 if (p_dev->uhid.fd < 0) {
664 log::error("Unexpected Set Report response");
665 return;
666 }
667
668 uint32_t* context =
669 (uint32_t*)fixed_queue_try_dequeue(p_dev->uhid.set_rpt_id_queue);
670
671 if (context == nullptr) {
672 log::warn("No pending UHID_SET_REPORT");
673 return;
674 }
675
676 struct uhid_event ev = {
677 .type = UHID_SET_REPORT_REPLY,
678 .u = {
679 .set_report_reply = {
680 .id = *context,
681 .err = status,
682 },
683 },
684 };
685 uhid_write(p_dev->uhid.fd, &ev);
686 osi_free(context);
687
688 #else
689 log::error("UHID_SET_REPORT_REPLY not supported");
690 #endif // ENABLE_UHID_SET_REPORT
691 }
692
693 /*******************************************************************************
694 *
695 * Function bta_hh_co_get_rpt_rsp
696 *
697 * Description This callout function is executed by HH when Get Report
698 * Response is received on Control Channel.
699 *
700 * Returns void.
701 *
702 ******************************************************************************/
bta_hh_co_get_rpt_rsp(uint8_t dev_handle,uint8_t status,const uint8_t * p_rpt,uint16_t len)703 void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status,
704 const uint8_t* p_rpt, uint16_t len) {
705 btif_hh_device_t* p_dev;
706
707 log::verbose("dev_handle = {}, status = {}", dev_handle, status);
708
709 p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
710 if (p_dev == nullptr) {
711 log::warn("Unknown HID device handle {}", dev_handle);
712 return;
713 }
714
715 if (!p_dev->uhid.get_rpt_id_queue) {
716 log::warn("Missing UHID_GET_REPORT id queue");
717 return;
718 }
719
720 // Send the HID report to the kernel.
721 if (p_dev->uhid.fd < 0) {
722 log::warn("Unexpected Get Report response");
723 return;
724 }
725
726 uint32_t* context =
727 (uint32_t*)fixed_queue_try_dequeue(p_dev->uhid.get_rpt_id_queue);
728
729 if (context == nullptr) {
730 log::warn("No pending UHID_GET_REPORT");
731 return;
732 }
733
734 if (len == 0 || len > UHID_DATA_MAX) {
735 log::warn("Invalid report size = {}", len);
736 return;
737 }
738
739 struct uhid_event ev = {
740 .type = UHID_FEATURE_ANSWER,
741 .u = {
742 .feature_answer = {
743 .id = *context,
744 .err = status,
745 .size = len,
746 },
747 },
748 };
749 memcpy(ev.u.feature_answer.data, p_rpt, len);
750
751 uhid_write(p_dev->uhid.fd, &ev);
752 osi_free(context);
753 }
754
755 /*******************************************************************************
756 *
757 * Function bta_hh_le_co_rpt_info
758 *
759 * Description This callout function is to convey the report information on
760 * a HOGP device to the application. Application can save this
761 * information in NV if device is bonded and load it back when
762 * stack reboot.
763 *
764 * Parameters link_spec - ACL link specification
765 * p_entry - report entry pointer
766 * app_id - application id
767 *
768 * Returns void.
769 *
770 ******************************************************************************/
bta_hh_le_co_rpt_info(const tAclLinkSpec & link_spec,tBTA_HH_RPT_CACHE_ENTRY * p_entry,uint8_t)771 void bta_hh_le_co_rpt_info(const tAclLinkSpec& link_spec,
772 tBTA_HH_RPT_CACHE_ENTRY* p_entry,
773 uint8_t /* app_id */) {
774 unsigned idx = 0;
775
776 std::string addrstr = link_spec.addrt.bda.ToString();
777 const char* bdstr = addrstr.c_str();
778
779 size_t len = btif_config_get_bin_length(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT);
780 if (len >= sizeof(tBTA_HH_RPT_CACHE_ENTRY) && len <= sizeof(sReportCache)) {
781 btif_config_get_bin(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT,
782 (uint8_t*)sReportCache, &len);
783 idx = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY);
784 }
785
786 if (idx < BTA_HH_NV_LOAD_MAX) {
787 memcpy(&sReportCache[idx++], p_entry, sizeof(tBTA_HH_RPT_CACHE_ENTRY));
788 btif_config_set_bin(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT,
789 (const uint8_t*)sReportCache,
790 idx * sizeof(tBTA_HH_RPT_CACHE_ENTRY));
791 btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT_VERSION,
792 BTA_HH_CACHE_REPORT_VERSION);
793 log::verbose("Saving report; dev={}, idx={}", link_spec, idx);
794 }
795 }
796
797 /*******************************************************************************
798 *
799 * Function bta_hh_le_co_cache_load
800 *
801 * Description This callout function is to request the application to load
802 * the cached HOGP report if there is any. When cache reading
803 * is completed, bta_hh_le_co_cache_load() is called by the
804 * application.
805 *
806 * Parameters link_spec - ACL link specification
807 * p_num_rpt - number of cached report
808 * app_id - application id
809 *
810 * Returns the cached report array
811 *
812 ******************************************************************************/
bta_hh_le_co_cache_load(const tAclLinkSpec & link_spec,uint8_t * p_num_rpt,uint8_t app_id)813 tBTA_HH_RPT_CACHE_ENTRY* bta_hh_le_co_cache_load(const tAclLinkSpec& link_spec,
814 uint8_t* p_num_rpt,
815 uint8_t app_id) {
816 std::string addrstr = link_spec.addrt.bda.ToString();
817 const char* bdstr = addrstr.c_str();
818
819 size_t len = btif_config_get_bin_length(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT);
820 if (!p_num_rpt || len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) return NULL;
821
822 if (len > sizeof(sReportCache)) len = sizeof(sReportCache);
823 btif_config_get_bin(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT,
824 (uint8_t*)sReportCache, &len);
825
826 int cache_version = -1;
827 btif_config_get_int(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT_VERSION,
828 &cache_version);
829
830 if (cache_version != BTA_HH_CACHE_REPORT_VERSION) {
831 bta_hh_le_co_reset_rpt_cache(link_spec, app_id);
832 return NULL;
833 }
834
835 *p_num_rpt = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY);
836
837 log::verbose("Loaded {} reports; dev={}", *p_num_rpt, link_spec);
838
839 return sReportCache;
840 }
841
842 /*******************************************************************************
843 *
844 * Function bta_hh_le_co_reset_rpt_cache
845 *
846 * Description This callout function is to reset the HOGP device cache.
847 *
848 * Parameters link_spec - ACL link specification
849 *
850 * Returns none
851 *
852 ******************************************************************************/
bta_hh_le_co_reset_rpt_cache(const tAclLinkSpec & link_spec,uint8_t)853 void bta_hh_le_co_reset_rpt_cache(const tAclLinkSpec& link_spec,
854 uint8_t /* app_id */) {
855 std::string addrstr = link_spec.addrt.bda.ToString();
856 const char* bdstr = addrstr.c_str();
857
858 btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT);
859 btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT_VERSION);
860 log::verbose("Reset cache for bda {}", link_spec);
861 }
862