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