1/****************************************************************************** 2 * 3 * Copyright (C) 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 <assert.h> 20#include <ctype.h> 21#include <errno.h> 22#include <fcntl.h> 23#include <linux/uhid.h> 24#include <pthread.h> 25#include <stdio.h> 26#include <string.h> 27#include <stdint.h> 28#include <sys/poll.h> 29#include <unistd.h> 30 31#include "btcore/include/bdaddr.h" 32#include "osi/include/osi.h" 33#include "bta_api.h" 34#include "bta_hh_api.h" 35#include "bta_hh_co.h" 36#include "btif_hh.h" 37#include "btif_util.h" 38 39const char *dev_path = "/dev/uhid"; 40 41#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) 42#include "btif_config.h" 43#define BTA_HH_NV_LOAD_MAX 16 44static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; 45#endif 46 47void uhid_set_non_blocking(int fd) 48{ 49 int opts = fcntl(fd, F_GETFL); 50 if (opts < 0) 51 APPL_TRACE_ERROR("%s() Getting flags failed (%s)", __func__, strerror(errno)); 52 53 opts |= O_NONBLOCK; 54 55 if (fcntl(fd, F_SETFL, opts) < 0) 56 APPL_TRACE_EVENT("%s() Setting non-blocking flag failed (%s)", __func__, strerror(errno)); 57} 58 59/*Internal function to perform UHID write and error checking*/ 60static int uhid_write(int fd, const struct uhid_event *ev) 61{ 62 ssize_t ret; 63 OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev))); 64 65 if (ret < 0){ 66 int rtn = -errno; 67 APPL_TRACE_ERROR("%s: Cannot write to uhid:%s", 68 __FUNCTION__, strerror(errno)); 69 return rtn; 70 } else if (ret != (ssize_t)sizeof(*ev)) { 71 APPL_TRACE_ERROR("%s: Wrong size written to uhid: %zd != %zu", 72 __FUNCTION__, ret, sizeof(*ev)); 73 return -EFAULT; 74 } 75 76 return 0; 77} 78 79/* Internal function to parse the events received from UHID driver*/ 80static int uhid_read_event(btif_hh_device_t *p_dev) 81{ 82 assert(p_dev); 83 84 struct uhid_event ev; 85 memset(&ev, 0, sizeof(ev)); 86 87 ssize_t ret; 88 OSI_NO_INTR(ret = read(p_dev->fd, &ev, sizeof(ev))); 89 90 if (ret == 0) { 91 APPL_TRACE_ERROR("%s: Read HUP on uhid-cdev %s", __FUNCTION__, 92 strerror(errno)); 93 return -EFAULT; 94 } else if (ret < 0) { 95 APPL_TRACE_ERROR("%s: Cannot read uhid-cdev: %s", __FUNCTION__, 96 strerror(errno)); 97 return -errno; 98 } else if ((ev.type == UHID_OUTPUT) || (ev.type==UHID_OUTPUT_EV)) { 99 // Only these two types havae payload, 100 // ensure we read full event descriptor 101 if (ret < (ssize_t)sizeof(ev)) { 102 APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %ld != %lu", 103 __FUNCTION__, ret, sizeof(ev.type)); 104 return -EFAULT; 105 } 106 } 107 108 switch (ev.type) { 109 case UHID_START: 110 APPL_TRACE_DEBUG("UHID_START from uhid-dev\n"); 111 p_dev->ready_for_data = TRUE; 112 break; 113 case UHID_STOP: 114 APPL_TRACE_DEBUG("UHID_STOP from uhid-dev\n"); 115 p_dev->ready_for_data = FALSE; 116 break; 117 case UHID_OPEN: 118 APPL_TRACE_DEBUG("UHID_OPEN from uhid-dev\n"); 119 p_dev->ready_for_data = TRUE; 120 break; 121 case UHID_CLOSE: 122 APPL_TRACE_DEBUG("UHID_CLOSE from uhid-dev\n"); 123 p_dev->ready_for_data = FALSE; 124 break; 125 case UHID_OUTPUT: 126 if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) { 127 APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", 128 __FUNCTION__, ret, 129 sizeof(ev.type) + sizeof(ev.u.output)); 130 return -EFAULT; 131 } 132 133 APPL_TRACE_DEBUG("UHID_OUTPUT: Report type = %d, report_size = %d" 134 ,ev.u.output.rtype, ev.u.output.size); 135 //Send SET_REPORT with feature report if the report type in output event is FEATURE 136 if(ev.u.output.rtype == UHID_FEATURE_REPORT) 137 btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT, 138 ev.u.output.size, ev.u.output.data); 139 else if(ev.u.output.rtype == UHID_OUTPUT_REPORT) 140 btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT, 141 ev.u.output.size, ev.u.output.data); 142 else 143 btif_hh_setreport(p_dev, BTHH_INPUT_REPORT, 144 ev.u.output.size, ev.u.output.data); 145 break; 146 case UHID_OUTPUT_EV: 147 APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n"); 148 break; 149 case UHID_FEATURE: 150 APPL_TRACE_DEBUG("UHID_FEATURE from uhid-dev\n"); 151 break; 152 case UHID_FEATURE_ANSWER: 153 APPL_TRACE_DEBUG("UHID_FEATURE_ANSWER from uhid-dev\n"); 154 break; 155 156 default: 157 APPL_TRACE_DEBUG("Invalid event from uhid-dev: %u\n", ev.type); 158 } 159 160 return 0; 161} 162 163/******************************************************************************* 164** 165** Function create_thread 166** 167** Description creat a select loop 168** 169** Returns pthread_t 170** 171*******************************************************************************/ 172static inline pthread_t create_thread(void *(*start_routine)(void *), void * arg){ 173 APPL_TRACE_DEBUG("create_thread: entered"); 174 pthread_attr_t thread_attr; 175 176 pthread_attr_init(&thread_attr); 177 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 178 pthread_t thread_id = -1; 179 if ( pthread_create(&thread_id, &thread_attr, start_routine, arg)!=0 ) 180 { 181 APPL_TRACE_ERROR("pthread_create : %s", strerror(errno)); 182 return -1; 183 } 184 APPL_TRACE_DEBUG("create_thread: thread created successfully"); 185 return thread_id; 186} 187 188/******************************************************************************* 189** 190** Function btif_hh_poll_event_thread 191** 192** Description the polling thread which polls for event from UHID driver 193** 194** Returns void 195** 196*******************************************************************************/ 197static void *btif_hh_poll_event_thread(void *arg) 198{ 199 btif_hh_device_t *p_dev = arg; 200 APPL_TRACE_DEBUG("%s: Thread created fd = %d", __func__, p_dev->fd); 201 struct pollfd pfds[1]; 202 203 pfds[0].fd = p_dev->fd; 204 pfds[0].events = POLLIN; 205 206 // Set the uhid fd as non-blocking to ensure we never block the BTU thread 207 uhid_set_non_blocking(p_dev->fd); 208 209 while(p_dev->hh_keep_polling){ 210 int ret; 211 OSI_NO_INTR(ret = poll(pfds, 1, 50)); 212 if (ret < 0) { 213 APPL_TRACE_ERROR("%s: Cannot poll for fds: %s\n", __func__, strerror(errno)); 214 break; 215 } 216 if (pfds[0].revents & POLLIN) { 217 APPL_TRACE_DEBUG("%s: POLLIN", __func__); 218 ret = uhid_read_event(p_dev); 219 if (ret != 0) 220 break; 221 } 222 } 223 224 p_dev->hh_poll_thread_id = -1; 225 return 0; 226} 227 228static inline void btif_hh_close_poll_thread(btif_hh_device_t *p_dev) 229{ 230 APPL_TRACE_DEBUG("%s", __FUNCTION__); 231 p_dev->hh_keep_polling = 0; 232 if(p_dev->hh_poll_thread_id > 0) 233 pthread_join(p_dev->hh_poll_thread_id,NULL); 234 235 return; 236} 237 238void bta_hh_co_destroy(int fd) 239{ 240 struct uhid_event ev; 241 memset(&ev, 0, sizeof(ev)); 242 ev.type = UHID_DESTROY; 243 uhid_write(fd, &ev); 244 APPL_TRACE_DEBUG("%s: Closing fd=%d", __func__, fd); 245 close(fd); 246} 247 248int bta_hh_co_write(int fd, UINT8* rpt, UINT16 len) 249{ 250 APPL_TRACE_DEBUG("%s: UHID write %d", __func__, len); 251 252 struct uhid_event ev; 253 memset(&ev, 0, sizeof(ev)); 254 ev.type = UHID_INPUT; 255 ev.u.input.size = len; 256 if(len > sizeof(ev.u.input.data)){ 257 APPL_TRACE_WARNING("%s: Report size greater than allowed size", 258 __FUNCTION__); 259 return -1; 260 } 261 memcpy(ev.u.input.data, rpt, len); 262 263 return uhid_write(fd, &ev); 264 265} 266 267 268/******************************************************************************* 269** 270** Function bta_hh_co_open 271** 272** Description When connection is opened, this call-out function is executed 273** by HH to do platform specific initialization. 274** 275** Returns void. 276*******************************************************************************/ 277void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_mask, 278 UINT8 app_id) 279{ 280 UINT32 i; 281 btif_hh_device_t *p_dev = NULL; 282 283 if (dev_handle == BTA_HH_INVALID_HANDLE) { 284 APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", 285 __FUNCTION__, dev_handle); 286 return; 287 } 288 289 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 290 p_dev = &btif_hh_cb.devices[i]; 291 if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && 292 p_dev->dev_handle == dev_handle) { 293 // We found a device with the same handle. Must be a device reconnected. 294 APPL_TRACE_WARNING("%s: Found an existing device with the same handle " 295 "dev_status = %d",__FUNCTION__, 296 p_dev->dev_status); 297 APPL_TRACE_WARNING("%s: bd_addr = [%02X:%02X:%02X:%02X:%02X:]", __FUNCTION__, 298 p_dev->bd_addr.address[0], p_dev->bd_addr.address[1], p_dev->bd_addr.address[2], 299 p_dev->bd_addr.address[3], p_dev->bd_addr.address[4]); 300 APPL_TRACE_WARNING("%s: attr_mask = 0x%04x, sub_class = 0x%02x, app_id = %d", 301 __FUNCTION__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id); 302 303 if(p_dev->fd<0) { 304 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC); 305 if (p_dev->fd < 0){ 306 APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", 307 __FUNCTION__,strerror(errno)); 308 return; 309 }else 310 APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd); 311 } 312 313 p_dev->hh_keep_polling = 1; 314 p_dev->hh_poll_thread_id = create_thread(btif_hh_poll_event_thread, p_dev); 315 break; 316 } 317 p_dev = NULL; 318 } 319 320 if (p_dev == NULL) { 321 // Did not find a device reconnection case. Find an empty slot now. 322 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 323 if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_UNKNOWN) { 324 p_dev = &btif_hh_cb.devices[i]; 325 p_dev->dev_handle = dev_handle; 326 p_dev->attr_mask = attr_mask; 327 p_dev->sub_class = sub_class; 328 p_dev->app_id = app_id; 329 p_dev->local_vup = FALSE; 330 331 btif_hh_cb.device_num++; 332 // This is a new device,open the uhid driver now. 333 p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC); 334 if (p_dev->fd < 0){ 335 APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", 336 __FUNCTION__,strerror(errno)); 337 return; 338 }else{ 339 APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd); 340 p_dev->hh_keep_polling = 1; 341 p_dev->hh_poll_thread_id = create_thread(btif_hh_poll_event_thread, p_dev); 342 } 343 344 345 break; 346 } 347 } 348 } 349 350 if (p_dev == NULL) { 351 APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __FUNCTION__); 352 return; 353 } 354 355 p_dev->dev_status = BTHH_CONN_STATE_CONNECTED; 356 APPL_TRACE_DEBUG("%s: Return device status %d", __FUNCTION__, p_dev->dev_status); 357} 358 359 360/******************************************************************************* 361** 362** Function bta_hh_co_close 363** 364** Description When connection is closed, this call-out function is executed 365** by HH to do platform specific finalization. 366** 367** Parameters dev_handle - device handle 368** app_id - application id 369** 370** Returns void. 371*******************************************************************************/ 372void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id) 373{ 374 UINT32 i; 375 btif_hh_device_t *p_dev = NULL; 376 377 APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __FUNCTION__, dev_handle, app_id); 378 if (dev_handle == BTA_HH_INVALID_HANDLE) { 379 APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __FUNCTION__, dev_handle); 380 return; 381 } 382 383 for (i = 0; i < BTIF_HH_MAX_HID; i++) { 384 p_dev = &btif_hh_cb.devices[i]; 385 if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) { 386 APPL_TRACE_WARNING("%s: Found an existing device with the same handle " 387 "dev_status = %d, dev_handle =%d" 388 ,__FUNCTION__,p_dev->dev_status 389 ,p_dev->dev_handle); 390 btif_hh_close_poll_thread(p_dev); 391 break; 392 } 393 } 394} 395 396 397/******************************************************************************* 398** 399** Function bta_hh_co_data 400** 401** Description This function is executed by BTA when HID host receive a data 402** report. 403** 404** Parameters dev_handle - device handle 405** *p_rpt - pointer to the report data 406** len - length of report data 407** mode - Hid host Protocol Mode 408** sub_clas - Device Subclass 409** app_id - application id 410** 411** Returns void 412*******************************************************************************/ 413void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, 414 UINT8 sub_class, UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id) 415{ 416 btif_hh_device_t *p_dev; 417 UNUSED(peer_addr); 418 419 APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " 420 "ctry_code = %d, app_id = %d", 421 __FUNCTION__, dev_handle, sub_class, mode, ctry_code, app_id); 422 423 p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); 424 if (p_dev == NULL) { 425 APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __FUNCTION__, dev_handle); 426 return; 427 } 428 429 // Send the HID data to the kernel. 430 if ((p_dev->fd >= 0) && p_dev->ready_for_data) { 431 bta_hh_co_write(p_dev->fd, p_rpt, len); 432 }else { 433 APPL_TRACE_WARNING("%s: Error: fd = %d, ready %d, len = %d", __FUNCTION__, p_dev->fd, 434 p_dev->ready_for_data, len); 435 } 436} 437 438 439/******************************************************************************* 440** 441** Function bta_hh_co_send_hid_info 442** 443** Description This function is called in btif_hh.c to process DSCP received. 444** 445** Parameters dev_handle - device handle 446** dscp_len - report descriptor length 447** *p_dscp - report descriptor 448** 449** Returns void 450*******************************************************************************/ 451void bta_hh_co_send_hid_info(btif_hh_device_t *p_dev, char *dev_name, UINT16 vendor_id, 452 UINT16 product_id, UINT16 version, UINT8 ctry_code, 453 int dscp_len, UINT8 *p_dscp) 454{ 455 int result; 456 struct uhid_event ev; 457 458 if (p_dev->fd < 0) { 459 APPL_TRACE_WARNING("%s: Error: fd = %d, dscp_len = %d", __FUNCTION__, p_dev->fd, dscp_len); 460 return; 461 } 462 463 APPL_TRACE_WARNING("%s: fd = %d, name = [%s], dscp_len = %d", __FUNCTION__, 464 p_dev->fd, dev_name, dscp_len); 465 APPL_TRACE_WARNING("%s: vendor_id = 0x%04x, product_id = 0x%04x, version= 0x%04x," 466 "ctry_code=0x%02x",__FUNCTION__, 467 vendor_id, product_id, 468 version, ctry_code); 469 470 //Create and send hid descriptor to kernel 471 memset(&ev, 0, sizeof(ev)); 472 ev.type = UHID_CREATE; 473 strncpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name) - 1); 474 snprintf((char*)ev.u.create.uniq, sizeof(ev.u.create.uniq), 475 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", 476 p_dev->bd_addr.address[5], p_dev->bd_addr.address[4], 477 p_dev->bd_addr.address[3], p_dev->bd_addr.address[2], 478 p_dev->bd_addr.address[1], p_dev->bd_addr.address[0]); 479 ev.u.create.rd_size = dscp_len; 480 ev.u.create.rd_data = p_dscp; 481 ev.u.create.bus = BUS_BLUETOOTH; 482 ev.u.create.vendor = vendor_id; 483 ev.u.create.product = product_id; 484 ev.u.create.version = version; 485 ev.u.create.country = ctry_code; 486 result = uhid_write(p_dev->fd, &ev); 487 488 APPL_TRACE_WARNING("%s: wrote descriptor to fd = %d, dscp_len = %d, result = %d", __FUNCTION__, 489 p_dev->fd, dscp_len, result); 490 491 if (result) { 492 APPL_TRACE_WARNING("%s: Error: failed to send DSCP, result = %d", __FUNCTION__, result); 493 494 /* The HID report descriptor is corrupted. Close the driver. */ 495 close(p_dev->fd); 496 p_dev->fd = -1; 497 } 498} 499 500#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) 501/******************************************************************************* 502** 503** Function bta_hh_le_co_rpt_info 504** 505** Description This callout function is to convey the report information on 506** a HOGP device to the application. Application can save this 507** information in NV if device is bonded and load it back when 508** stack reboot. 509** 510** Parameters remote_bda - remote device address 511** p_entry - report entry pointer 512** app_id - application id 513** 514** Returns void. 515** 516*******************************************************************************/ 517void bta_hh_le_co_rpt_info(BD_ADDR remote_bda, tBTA_HH_RPT_CACHE_ENTRY *p_entry, UINT8 app_id) 518{ 519 UNUSED(app_id); 520 521 unsigned idx = 0; 522 523 bdstr_t bdstr; 524 sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", 525 remote_bda[0], remote_bda[1], remote_bda[2], 526 remote_bda[3], remote_bda[4], remote_bda[5]); 527 528 size_t len = btif_config_get_bin_length(bdstr, "HidReport"); 529 if (len >= sizeof(tBTA_HH_RPT_CACHE_ENTRY) && len <= sizeof(sReportCache)) 530 { 531 btif_config_get_bin(bdstr, "HidReport", (uint8_t *)sReportCache, &len); 532 idx = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY); 533 } 534 535 if (idx < BTA_HH_NV_LOAD_MAX) 536 { 537 memcpy(&sReportCache[idx++], p_entry, sizeof(tBTA_HH_RPT_CACHE_ENTRY)); 538 btif_config_set_bin(bdstr, "HidReport", (const uint8_t *)sReportCache, 539 idx * sizeof(tBTA_HH_RPT_CACHE_ENTRY)); 540 BTIF_TRACE_DEBUG("%s() - Saving report; dev=%s, idx=%d", __FUNCTION__, bdstr, idx); 541 } 542} 543 544 545/******************************************************************************* 546** 547** Function bta_hh_le_co_cache_load 548** 549** Description This callout function is to request the application to load the 550** cached HOGP report if there is any. When cache reading is completed, 551** bta_hh_le_ci_cache_load() is called by the application. 552** 553** Parameters remote_bda - remote device address 554** p_num_rpt: number of cached report 555** app_id - application id 556** 557** Returns the acched report array 558** 559*******************************************************************************/ 560tBTA_HH_RPT_CACHE_ENTRY * bta_hh_le_co_cache_load (BD_ADDR remote_bda, 561 UINT8 *p_num_rpt, UINT8 app_id) 562{ 563 UNUSED(app_id); 564 565 bdstr_t bdstr; 566 sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", 567 remote_bda[0], remote_bda[1], remote_bda[2], 568 remote_bda[3], remote_bda[4], remote_bda[5]); 569 570 size_t len = btif_config_get_bin_length(bdstr, "HidReport"); 571 if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) 572 return NULL; 573 574 if (len > sizeof(sReportCache)) 575 len = sizeof(sReportCache); 576 btif_config_get_bin(bdstr, "HidReport", (uint8_t *)sReportCache, &len); 577 *p_num_rpt = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY); 578 579 BTIF_TRACE_DEBUG("%s() - Loaded %d reports; dev=%s", __FUNCTION__, *p_num_rpt, bdstr); 580 581 return sReportCache; 582} 583 584/******************************************************************************* 585** 586** Function bta_hh_le_co_reset_rpt_cache 587** 588** Description This callout function is to reset the HOGP device cache. 589** 590** Parameters remote_bda - remote device address 591** 592** Returns none 593** 594*******************************************************************************/ 595void bta_hh_le_co_reset_rpt_cache (BD_ADDR remote_bda, UINT8 app_id) 596{ 597 UNUSED(app_id); 598 599 bdstr_t bdstr; 600 sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", 601 remote_bda[0], remote_bda[1], remote_bda[2], 602 remote_bda[3], remote_bda[4], remote_bda[5]); 603 btif_config_remove(bdstr, "HidReport"); 604 605 BTIF_TRACE_DEBUG("%s() - Reset cache for bda %s", __FUNCTION__, bdstr); 606} 607#endif /* #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */ 608 609