1 /*
2 * Copyright (C) 2014 Andrew Duggan
3 * Copyright (C) 2014 Synaptics Inc
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 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/ioctl.h>
27 #include <sys/select.h>
28
29 #include <linux/types.h>
30 #include <linux/input.h>
31 #include <linux/hidraw.h>
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <sys/inotify.h>
35
36 #include "hiddevice.h"
37
38 #define RMI_WRITE_REPORT_ID 0x9 // Output Report
39 #define RMI_READ_ADDR_REPORT_ID 0xa // Output Report
40 #define RMI_READ_DATA_REPORT_ID 0xb // Input Report
41 #define RMI_ATTN_REPORT_ID 0xc // Input Report
42 #define RMI_SET_RMI_MODE_REPORT_ID 0xf // Feature Report
43
44 enum hid_report_type {
45 HID_REPORT_TYPE_UNKNOWN = 0x0,
46 HID_REPORT_TYPE_INPUT = 0x81,
47 HID_REPORT_TYPE_OUTPUT = 0x91,
48 HID_REPORT_TYPE_FEATURE = 0xb1,
49 };
50
51 #define HID_RMI4_REPORT_ID 0
52 #define HID_RMI4_READ_INPUT_COUNT 1
53 #define HID_RMI4_READ_INPUT_DATA 2
54 #define HID_RMI4_READ_OUTPUT_ADDR 2
55 #define HID_RMI4_READ_OUTPUT_COUNT 4
56 #define HID_RMI4_WRITE_OUTPUT_COUNT 1
57 #define HID_RMI4_WRITE_OUTPUT_ADDR 2
58 #define HID_RMI4_WRITE_OUTPUT_DATA 4
59 #define HID_RMI4_FEATURE_MODE 1
60 #define HID_RMI4_ATTN_INTERUPT_SOURCES 1
61 #define HID_RMI4_ATTN_DATA 2
62
63 #define SYNAPTICS_VENDOR_ID 0x06cb
64
Open(const char * filename)65 int HIDDevice::Open(const char * filename)
66 {
67 int rc;
68 int desc_size;
69 std::string hidDeviceName;
70 std::string hidDriverName;
71
72 if (!filename)
73 return -EINVAL;
74
75 m_fd = open(filename, O_RDWR);
76 if (m_fd < 0)
77 return -1;
78
79 memset(&m_rptDesc, 0, sizeof(m_rptDesc));
80 memset(&m_info, 0, sizeof(m_info));
81
82 rc = ioctl(m_fd, HIDIOCGRDESCSIZE, &desc_size);
83 if (rc < 0)
84 goto error;
85
86 m_rptDesc.size = desc_size;
87 rc = ioctl(m_fd, HIDIOCGRDESC, &m_rptDesc);
88 if (rc < 0)
89 goto error;
90
91 rc = ioctl(m_fd, HIDIOCGRAWINFO, &m_info);
92 if (rc < 0)
93 goto error;
94
95 if (m_info.vendor != SYNAPTICS_VENDOR_ID) {
96 errno = -ENODEV;
97 rc = -1;
98 goto error;
99 }
100
101 ParseReportDescriptor();
102
103 m_inputReport = new unsigned char[m_inputReportSize]();
104 if (!m_inputReport) {
105 errno = -ENOMEM;
106 rc = -1;
107 goto error;
108 }
109
110 m_outputReport = new unsigned char[m_outputReportSize]();
111 if (!m_outputReport) {
112 errno = -ENOMEM;
113 rc = -1;
114 goto error;
115 }
116
117 m_readData = new unsigned char[m_inputReportSize]();
118 if (!m_readData) {
119 errno = -ENOMEM;
120 rc = -1;
121 goto error;
122 }
123
124 m_attnData = new unsigned char[m_inputReportSize]();
125 if (!m_attnData) {
126 errno = -ENOMEM;
127 rc = -1;
128 goto error;
129 }
130
131 m_deviceOpen = true;
132
133 // Determine which mode the device is currently running in based on the current HID driver
134 // hid-rmi indicated RMI Mode 1 all others would be Mode 0
135 if (LookupHidDeviceName(m_info.bustype, m_info.vendor, m_info.product, hidDeviceName)) {
136 if (LookupHidDriverName(hidDeviceName, hidDriverName)) {
137 if (hidDriverName == "hid-rmi")
138 m_initialMode = HID_RMI4_MODE_ATTN_REPORTS;
139 }
140 }
141
142 if (m_initialMode != m_mode) {
143 rc = SetMode(m_mode);
144 if (rc) {
145 rc = -1;
146 goto error;
147 }
148 }
149
150 return 0;
151
152 error:
153 Close();
154 return rc;
155 }
156
ParseReportDescriptor()157 void HIDDevice::ParseReportDescriptor()
158 {
159 bool isVendorSpecific = false;
160 bool isReport = false;
161 int totalReportSize = 0;
162 int reportSize = 0;
163 int reportCount = 0;
164 enum hid_report_type hidReportType = HID_REPORT_TYPE_UNKNOWN;
165 bool inCollection = false;
166
167 for (unsigned int i = 0; i < m_rptDesc.size; ++i) {
168 if (m_rptDesc.value[i] == 0xc0) {
169 inCollection = false;
170 isVendorSpecific = false;
171 isReport = false;
172 continue;
173 }
174
175 if (isVendorSpecific) {
176 if (m_rptDesc.value[i] == 0x85) {
177 if (isReport) {
178 // finish up data on the previous report
179 totalReportSize = (reportSize * reportCount) >> 3;
180
181 switch (hidReportType) {
182 case HID_REPORT_TYPE_INPUT:
183 m_inputReportSize = totalReportSize + 1;
184 break;
185 case HID_REPORT_TYPE_OUTPUT:
186 m_outputReportSize = totalReportSize + 1;
187 break;
188 case HID_REPORT_TYPE_FEATURE:
189 m_featureReportSize = totalReportSize + 1;
190 break;
191 case HID_REPORT_TYPE_UNKNOWN:
192 default:
193 break;
194 }
195 }
196
197 // reset values for the new report
198 totalReportSize = 0;
199 reportSize = 0;
200 reportCount = 0;
201 hidReportType = HID_REPORT_TYPE_UNKNOWN;
202
203 isReport = true;
204 }
205
206 if (isReport) {
207 if (m_rptDesc.value[i] == 0x75) {
208 if (i + 1 >= m_rptDesc.size)
209 return;
210 reportSize = m_rptDesc.value[++i];
211 continue;
212 }
213
214 if (m_rptDesc.value[i] == 0x95) {
215 if (i + 1 >= m_rptDesc.size)
216 return;
217 reportCount = m_rptDesc.value[++i];
218 continue;
219 }
220
221 if (m_rptDesc.value[i] == HID_REPORT_TYPE_INPUT)
222 hidReportType = HID_REPORT_TYPE_INPUT;
223
224 if (m_rptDesc.value[i] == HID_REPORT_TYPE_OUTPUT)
225 hidReportType = HID_REPORT_TYPE_OUTPUT;
226
227 if (m_rptDesc.value[i] == HID_REPORT_TYPE_FEATURE) {
228 hidReportType = HID_REPORT_TYPE_FEATURE;
229 }
230 }
231 }
232
233 if (!inCollection) {
234 switch (m_rptDesc.value[i]) {
235 case 0x00:
236 case 0x01:
237 case 0x02:
238 case 0x03:
239 case 0x04:
240 inCollection = true;
241 break;
242 case 0x05:
243 inCollection = true;
244
245 if (i + 3 >= m_rptDesc.size)
246 break;
247
248 // touchscreens with active pen have a Generic Mouse collection
249 // so stop searching if we have already found the touchscreen digitizer
250 // usage.
251 if (m_deviceType == RMI_DEVICE_TYPE_TOUCHSCREEN)
252 break;
253
254 if (m_rptDesc.value[i + 1] == 0x01) {
255 if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x02)
256 m_deviceType = RMI_DEVICE_TYPE_TOUCHPAD;
257 } else if (m_rptDesc.value[i + 1] == 0x0d) {
258 if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x04)
259 m_deviceType = RMI_DEVICE_TYPE_TOUCHSCREEN;
260 // for Precision Touch Pad
261 else if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x05)
262 m_deviceType = RMI_DEVICE_TYPE_TOUCHPAD;
263 }
264 i += 3;
265 break;
266 case 0x06:
267 inCollection = true;
268 if (i + 2 >= m_rptDesc.size)
269 break;
270
271 if (m_rptDesc.value[i + 1] == 0x00 && m_rptDesc.value[i + 2] == 0xFF)
272 isVendorSpecific = true;
273 i += 2;
274 break;
275 default:
276 break;
277
278 }
279 }
280 }
281 }
282
Read(unsigned short addr,unsigned char * buf,unsigned short len)283 int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len)
284 {
285 ssize_t count;
286 size_t bytesReadPerRequest;
287 size_t bytesInDataReport;
288 size_t totalBytesRead;
289 size_t bytesPerRequest;
290 size_t bytesWritten;
291 size_t bytesToRequest;
292 int reportId;
293 int rc;
294
295 if (!m_deviceOpen)
296 return -1;
297
298 if (m_bytesPerReadRequest)
299 bytesPerRequest = m_bytesPerReadRequest;
300 else
301 bytesPerRequest = len;
302
303 for (totalBytesRead = 0; totalBytesRead < len; totalBytesRead += bytesReadPerRequest) {
304 count = 0;
305 if ((len - totalBytesRead) < bytesPerRequest)
306 bytesToRequest = len % bytesPerRequest;
307 else
308 bytesToRequest = bytesPerRequest;
309
310 if (m_outputReportSize < HID_RMI4_READ_OUTPUT_COUNT + 2) {
311 return -1;
312 }
313 m_outputReport[HID_RMI4_REPORT_ID] = RMI_READ_ADDR_REPORT_ID;
314 m_outputReport[1] = 0; /* old 1 byte read count */
315 m_outputReport[HID_RMI4_READ_OUTPUT_ADDR] = addr & 0xFF;
316 m_outputReport[HID_RMI4_READ_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF;
317 m_outputReport[HID_RMI4_READ_OUTPUT_COUNT] = bytesToRequest & 0xFF;
318 m_outputReport[HID_RMI4_READ_OUTPUT_COUNT + 1] = (bytesToRequest >> 8) & 0xFF;
319
320 m_dataBytesRead = 0;
321
322 for (bytesWritten = 0; bytesWritten < m_outputReportSize; bytesWritten += count) {
323 m_bCancel = false;
324 count = write(m_fd, m_outputReport + bytesWritten,
325 m_outputReportSize - bytesWritten);
326 if (count < 0) {
327 if (errno == EINTR && m_deviceOpen && !m_bCancel)
328 continue;
329 else
330 return count;
331 }
332 break;
333 }
334
335 bytesReadPerRequest = 0;
336 while (bytesReadPerRequest < bytesToRequest) {
337 rc = GetReport(&reportId);
338 if (rc > 0 && reportId == RMI_READ_DATA_REPORT_ID) {
339 if (static_cast<ssize_t>(m_inputReportSize) <
340 std::max(HID_RMI4_READ_INPUT_COUNT,
341 HID_RMI4_READ_INPUT_DATA)){
342 return -1;
343 }
344 bytesInDataReport = m_readData[HID_RMI4_READ_INPUT_COUNT];
345 if (bytesInDataReport > bytesToRequest
346 || bytesReadPerRequest + bytesInDataReport > len){
347 return -1;
348 }
349 memcpy(buf + bytesReadPerRequest, &m_readData[HID_RMI4_READ_INPUT_DATA],
350 bytesInDataReport);
351 bytesReadPerRequest += bytesInDataReport;
352 m_dataBytesRead = 0;
353 }
354 }
355 addr += bytesPerRequest;
356 }
357
358 return totalBytesRead;
359 }
360
Write(unsigned short addr,const unsigned char * buf,unsigned short len)361 int HIDDevice::Write(unsigned short addr, const unsigned char *buf, unsigned short len)
362 {
363 ssize_t count;
364
365 if (!m_deviceOpen)
366 return -1;
367
368 if (static_cast<ssize_t>(m_outputReportSize) <
369 HID_RMI4_WRITE_OUTPUT_DATA + len)
370 return -1;
371 m_outputReport[HID_RMI4_REPORT_ID] = RMI_WRITE_REPORT_ID;
372 m_outputReport[HID_RMI4_WRITE_OUTPUT_COUNT] = len;
373 m_outputReport[HID_RMI4_WRITE_OUTPUT_ADDR] = addr & 0xFF;
374 m_outputReport[HID_RMI4_WRITE_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF;
375 memcpy(&m_outputReport[HID_RMI4_WRITE_OUTPUT_DATA], buf, len);
376
377 for (;;) {
378 m_bCancel = false;
379 count = write(m_fd, m_outputReport, m_outputReportSize);
380 if (count < 0) {
381 if (errno == EINTR && m_deviceOpen && !m_bCancel)
382 continue;
383 else
384 return count;
385 }
386 return len;
387 }
388 }
389
SetMode(int mode)390 int HIDDevice::SetMode(int mode)
391 {
392 int rc;
393 char buf[2];
394
395 if (!m_deviceOpen)
396 return -1;
397
398 buf[0] = 0xF;
399 buf[1] = mode;
400 rc = ioctl(m_fd, HIDIOCSFEATURE(2), buf);
401 if (rc < 0) {
402 perror("HIDIOCSFEATURE");
403 return rc;
404 }
405
406 return 0;
407 }
408
Close()409 void HIDDevice::Close()
410 {
411 RMIDevice::Close();
412
413 if (!m_deviceOpen)
414 return;
415
416 if (m_initialMode != m_mode)
417 SetMode(m_initialMode);
418
419 m_deviceOpen = false;
420 close(m_fd);
421 m_fd = -1;
422
423 delete[] m_inputReport;
424 m_inputReport = NULL;
425 delete[] m_outputReport;
426 m_outputReport = NULL;
427 delete[] m_readData;
428 m_readData = NULL;
429 delete[] m_attnData;
430 m_attnData = NULL;
431 }
432
WaitForAttention(struct timeval * timeout,unsigned int source_mask)433 int HIDDevice::WaitForAttention(struct timeval * timeout, unsigned int source_mask)
434 {
435 return GetAttentionReport(timeout, source_mask, NULL, NULL);
436 }
437
GetAttentionReport(struct timeval * timeout,unsigned int source_mask,unsigned char * buf,unsigned int * len)438 int HIDDevice::GetAttentionReport(struct timeval * timeout, unsigned int source_mask,
439 unsigned char *buf, unsigned int *len)
440 {
441 int rc = 0;
442 int reportId;
443
444 // Assume the Linux implementation of select with timeout set to the
445 // time remaining.
446 while (!timeout || (timeout->tv_sec != 0 || timeout->tv_usec != 0)) {
447 rc = GetReport(&reportId, timeout);
448 if (rc > 0) {
449 if (reportId == RMI_ATTN_REPORT_ID) {
450 // If a valid buffer is passed in then copy the data from
451 // the attention report into it. If the buffer is
452 // too small simply set *len to 0 to indicate nothing
453 // was copied. Some callers won't care about the contents
454 // of the report so failing to copy the data should not return
455 // an error.
456 if (buf && len) {
457 if (*len >= m_inputReportSize) {
458 *len = m_inputReportSize;
459 memcpy(buf, m_attnData, *len);
460 } else {
461 *len = 0;
462 }
463 }
464
465 if (m_inputReportSize < HID_RMI4_ATTN_INTERUPT_SOURCES + 1)
466 return -1;
467
468 if (source_mask & m_attnData[HID_RMI4_ATTN_INTERUPT_SOURCES])
469 return rc;
470 }
471 } else {
472 return rc;
473 }
474 }
475
476 return rc;
477 }
478
GetReport(int * reportId,struct timeval * timeout)479 int HIDDevice::GetReport(int *reportId, struct timeval * timeout)
480 {
481 ssize_t count = 0;
482 fd_set fds;
483 int rc;
484
485 if (!m_deviceOpen)
486 return -1;
487
488 if (m_inputReportSize < HID_RMI4_REPORT_ID + 1)
489 return -1;
490
491 for (;;) {
492 FD_ZERO(&fds);
493 FD_SET(m_fd, &fds);
494
495 rc = select(m_fd + 1, &fds, NULL, NULL, timeout);
496 if (rc == 0) {
497 return -ETIMEDOUT;
498 } else if (rc < 0) {
499 if (errno == EINTR && m_deviceOpen && !m_bCancel)
500 continue;
501 else
502 return rc;
503 } else if (rc > 0 && FD_ISSET(m_fd, &fds)) {
504 size_t offset = 0;
505 for (;;) {
506 m_bCancel = false;
507 count = read(m_fd, m_inputReport + offset, m_inputReportSize - offset);
508 if (count < 0) {
509 if (errno == EINTR && m_deviceOpen && !m_bCancel)
510 continue;
511 else
512 return count;
513 }
514 offset += count;
515 if (offset == m_inputReportSize)
516 break;
517 }
518 count = offset;
519 }
520 break;
521 }
522
523 if (reportId)
524 *reportId = m_inputReport[HID_RMI4_REPORT_ID];
525
526 if (m_inputReport[HID_RMI4_REPORT_ID] == RMI_ATTN_REPORT_ID) {
527 if (static_cast<ssize_t>(m_inputReportSize) < count)
528 return -1;
529 memcpy(m_attnData, m_inputReport, count);
530 } else if (m_inputReport[HID_RMI4_REPORT_ID] == RMI_READ_DATA_REPORT_ID) {
531 if (static_cast<ssize_t>(m_inputReportSize) < count)
532 return -1;
533 memcpy(m_readData, m_inputReport, count);
534 m_dataBytesRead = count;
535 }
536 return 1;
537 }
538
PrintReport(const unsigned char * report)539 void HIDDevice::PrintReport(const unsigned char *report)
540 {
541 int i;
542 int len = 0;
543 const unsigned char * data;
544 int addr = 0;
545
546 switch (report[HID_RMI4_REPORT_ID]) {
547 case RMI_WRITE_REPORT_ID:
548 len = report[HID_RMI4_WRITE_OUTPUT_COUNT];
549 data = &report[HID_RMI4_WRITE_OUTPUT_DATA];
550 addr = (report[HID_RMI4_WRITE_OUTPUT_ADDR] & 0xFF)
551 | ((report[HID_RMI4_WRITE_OUTPUT_ADDR + 1] & 0xFF) << 8);
552 fprintf(stdout, "Write Report:\n");
553 fprintf(stdout, "Address = 0x%02X\n", addr);
554 fprintf(stdout, "Length = 0x%02X\n", len);
555 break;
556 case RMI_READ_ADDR_REPORT_ID:
557 addr = (report[HID_RMI4_READ_OUTPUT_ADDR] & 0xFF)
558 | ((report[HID_RMI4_READ_OUTPUT_ADDR + 1] & 0xFF) << 8);
559 len = (report[HID_RMI4_READ_OUTPUT_COUNT] & 0xFF)
560 | ((report[HID_RMI4_READ_OUTPUT_COUNT + 1] & 0xFF) << 8);
561 fprintf(stdout, "Read Request (Output Report):\n");
562 fprintf(stdout, "Address = 0x%02X\n", addr);
563 fprintf(stdout, "Length = 0x%02X\n", len);
564 return;
565 break;
566 case RMI_READ_DATA_REPORT_ID:
567 len = report[HID_RMI4_READ_INPUT_COUNT];
568 data = &report[HID_RMI4_READ_INPUT_DATA];
569 fprintf(stdout, "Read Data Report:\n");
570 fprintf(stdout, "Length = 0x%02X\n", len);
571 break;
572 case RMI_ATTN_REPORT_ID:
573 fprintf(stdout, "Attention Report:\n");
574 len = 28;
575 data = &report[HID_RMI4_ATTN_DATA];
576 fprintf(stdout, "Interrupt Sources: 0x%02X\n",
577 report[HID_RMI4_ATTN_INTERUPT_SOURCES]);
578 break;
579 default:
580 fprintf(stderr, "Unknown Report: ID 0x%02x\n", report[HID_RMI4_REPORT_ID]);
581 return;
582 }
583
584 fprintf(stdout, "Data:\n");
585 for (i = 0; i < len; ++i) {
586 fprintf(stdout, "0x%02X ", data[i]);
587 if (i % 8 == 7) {
588 fprintf(stdout, "\n");
589 }
590 }
591 fprintf(stdout, "\n\n");
592 }
593
594 // Print protocol specific device information
PrintDeviceInfo()595 void HIDDevice::PrintDeviceInfo()
596 {
597 enum RMIDeviceType deviceType = GetDeviceType();
598
599 fprintf(stdout, "HID device info:\nBus: %s Vendor: 0x%04x Product: 0x%04x\n",
600 m_info.bustype == BUS_I2C ? "I2C" : "USB", m_info.vendor, m_info.product);
601 fprintf(stdout, "Report sizes: input: %ld output: %ld\n", (unsigned long)m_inputReportSize,
602 (unsigned long)m_outputReportSize);
603 if (deviceType)
604 fprintf(stdout, "device type: %s\n", deviceType == RMI_DEVICE_TYPE_TOUCHSCREEN ?
605 "touchscreen" : "touchpad");
606 }
607
WriteDeviceNameToFile(const char * file,const char * str)608 bool WriteDeviceNameToFile(const char * file, const char * str)
609 {
610 int fd;
611 ssize_t size;
612
613 fd = open(file, O_WRONLY);
614 if (fd < 0)
615 return false;
616
617 for (;;) {
618 size = write(fd, str, strlen(str));
619 if (size < 0) {
620 if (errno == EINTR)
621 continue;
622
623 return false;
624 }
625 break;
626 }
627
628 return close(fd) == 0 && size == static_cast<ssize_t>(strlen(str));
629 }
630 static const char * const absval[6] = { "Value", "Min ", "Max ", "Fuzz ", "Flat ", "Resolution "};
631 #define KEY_MAX 0x2ff
632 #define EV_MAX 0x1f
633 #define BITS_PER_LONG (sizeof(long) * 8)
634 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
635 #define OFF(x) ((x)%BITS_PER_LONG)
636 #define BIT(x) (1UL<<OFF(x))
637 #define LONG(x) ((x)/BITS_PER_LONG)
638 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
639 #define DEV_INPUT_EVENT "/dev/input"
640 #define EVENT_DEV_NAME "event"
641 /**
642 * Filter for the AutoDevProbe scandir on /dev/input.
643 *
644 * @param dir The current directory entry provided by scandir.
645 *
646 * @return Non-zero if the given directory entry starts with "event", or zero
647 * otherwise.
648 */
is_event_device(const struct dirent * dir)649 static int is_event_device(const struct dirent *dir) {
650 return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
651 }
652
CheckABSEvent()653 bool HIDDevice::CheckABSEvent()
654 {
655 int fd=-1;
656 unsigned int type;
657 int abs[6] = {0};
658 int k;
659 struct dirent **namelist;
660 int i, ndev, devnum, match;
661 char *filename;
662 int max_device = 0;
663 char input_event_name[PATH_MAX];
664 unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
665
666
667 #ifdef __BIONIC__
668 // Android's libc doesn't have the GNU versionsort extension.
669 ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, alphasort);
670 #else
671 ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, versionsort);
672 #endif
673 if (ndev <= 0)
674 return false;
675 for (i = 0; i < ndev; i++)
676 {
677 char fname[64];
678 int fd = -1;
679 char name[256] = "???";
680
681 snprintf(fname, sizeof(fname),
682 "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
683 fd = open(fname, O_RDONLY);
684 if (fd < 0)
685 continue;
686 ioctl(fd, EVIOCGNAME(sizeof(name)), name);
687 //fprintf(stderr, "%s: %s\n", fname, name);
688 close(fd);
689
690 if(strstr(name, m_transportDeviceName.c_str()+4))
691 {
692 snprintf(input_event_name, sizeof(fname), "%s", fname);
693 }
694 free(namelist[i]);
695 }
696
697 if ((fd = open(input_event_name, O_RDONLY)) < 0) {
698 if (errno == EACCES && getuid() != 0)
699 fprintf(stderr, "No access right \n");
700 }
701 memset(bit, 0, sizeof(bit));
702 ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
703 for (type = 0; type < EV_MAX; type++) {
704 if (test_bit(type, bit[0]) && type == EV_ABS) {
705 ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit[type]);
706 if (test_bit(ABS_X, bit[type])) {
707 ioctl(fd, EVIOCGABS(ABS_X), abs);
708 if(abs[2] == 0) //maximum
709 {
710 Sleep(1000);
711 return false;
712 }
713 }
714 }
715 }
716 return true;
717 }
RebindDriver()718 void HIDDevice::RebindDriver()
719 {
720 int bus = m_info.bustype;
721 int vendor = m_info.vendor;
722 int product = m_info.product;
723 std::string hidDeviceName;
724 std::string bindFile;
725 std::string unbindFile;
726 std::string hidrawFile;
727 int notifyFd;
728 int wd;
729 int rc;
730 Close();
731
732 notifyFd = inotify_init();
733 if (notifyFd < 0) {
734 fprintf(stderr, "Failed to initialize inotify\n");
735 return;
736 }
737
738 wd = inotify_add_watch(notifyFd, "/dev", IN_CREATE);
739 if (wd < 0) {
740 fprintf(stderr, "Failed to add watcher for /dev\n");
741 return;
742 }
743
744 if (m_transportDeviceName == "") {
745 if (!LookupHidDeviceName(bus, vendor, product, hidDeviceName)) {
746 fprintf(stderr, "Failed to find HID device name for the specified device: bus (0x%x) vendor: (0x%x) product: (0x%x)\n",
747 bus, vendor, product);
748 return;
749 }
750
751 if (!FindTransportDevice(bus, hidDeviceName, m_transportDeviceName, m_driverPath)) {
752 fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str());
753 return;
754 }
755
756 }
757
758 bindFile = m_driverPath + "bind";
759 unbindFile = m_driverPath + "unbind";
760
761 Sleep(500);
762 if (!WriteDeviceNameToFile(unbindFile.c_str(), m_transportDeviceName.c_str())) {
763 fprintf(stderr, "Failed to unbind HID device %s: %s\n",
764 m_transportDeviceName.c_str(), strerror(errno));
765 return;
766 }
767 Sleep(500);
768 if (!WriteDeviceNameToFile(bindFile.c_str(), m_transportDeviceName.c_str())) {
769 fprintf(stderr, "Failed to bind HID device %s: %s\n",
770 m_transportDeviceName.c_str(), strerror(errno));
771 return;
772 }
773
774 if (WaitForHidRawDevice(notifyFd, hidrawFile)) {
775 rc = Open(hidrawFile.c_str());
776 if (rc)
777 fprintf(stderr, "Failed to open device (%s) during rebind: %d: errno: %s (%d)\n",
778 hidrawFile.c_str(), rc, strerror(errno), errno);
779 }
780 }
781
FindTransportDevice(uint32_t bus,std::string & hidDeviceName,std::string & transportDeviceName,std::string & driverPath)782 bool HIDDevice::FindTransportDevice(uint32_t bus, std::string & hidDeviceName,
783 std::string & transportDeviceName, std::string & driverPath)
784 {
785 std::string devicePrefix = "/sys/bus/";
786 std::string devicePath;
787 struct dirent * devicesDirEntry;
788 DIR * devicesDir;
789 struct dirent * devDirEntry;
790 DIR * devDir;
791 bool deviceFound = false;
792 ssize_t sz;
793
794 if (bus == BUS_I2C) {
795 devicePrefix += "i2c/";
796 // From new patch released on 2020/11, i2c_hid would be renamed as i2c_hid_acpi,
797 // and also need backward compatible.
798 std::string driverPathTemp = devicePrefix + "drivers/i2c_hid/";
799 DIR *driverPathtest = opendir(driverPathTemp.c_str());
800 if(!driverPathtest) {
801 driverPath = devicePrefix + "drivers/i2c_hid_acpi/";
802 } else {
803 driverPath = devicePrefix + "drivers/i2c_hid/";
804 }
805 } else {
806 devicePrefix += "usb/";
807 driverPath = devicePrefix + "drivers/usbhid/";
808 }
809 devicePath = devicePrefix + "devices/";
810
811 devicesDir = opendir(devicePath.c_str());
812 if (!devicesDir)
813 return false;
814
815 while((devicesDirEntry = readdir(devicesDir)) != NULL) {
816 if (devicesDirEntry->d_type != DT_LNK)
817 continue;
818
819 char buf[PATH_MAX];
820
821 sz = readlinkat(dirfd(devicesDir), devicesDirEntry->d_name, buf, PATH_MAX);
822 if (sz < 0)
823 continue;
824
825 buf[sz] = 0;
826
827 std::string fullLinkPath = devicePath + buf;
828 devDir = opendir(fullLinkPath.c_str());
829 if (!devDir) {
830 fprintf(stdout, "opendir failed\n");
831 continue;
832 }
833
834 while ((devDirEntry = readdir(devDir)) != NULL) {
835 if (!strcmp(devDirEntry->d_name, hidDeviceName.c_str())) {
836 transportDeviceName = devicesDirEntry->d_name;
837 deviceFound = true;
838 break;
839 }
840 }
841 closedir(devDir);
842
843 if (deviceFound)
844 break;
845 }
846 closedir(devicesDir);
847
848 return deviceFound;
849 }
850
LookupHidDeviceName(uint32_t bus,int16_t vendorId,int16_t productId,std::string & deviceName)851 bool HIDDevice::LookupHidDeviceName(uint32_t bus, int16_t vendorId, int16_t productId, std::string & deviceName)
852 {
853 bool ret = false;
854 struct dirent * devDirEntry;
855 DIR * devDir;
856 char devicePrefix[15];
857
858 snprintf(devicePrefix, 15, "%04X:%04X:%04X", bus, (vendorId & 0xFFFF), (productId & 0xFFFF));
859
860 devDir = opendir("/sys/bus/hid/devices");
861 if (!devDir)
862 return false;
863
864 while ((devDirEntry = readdir(devDir)) != NULL) {
865 if (!strncmp(devDirEntry->d_name, devicePrefix, 14)) {
866 deviceName = devDirEntry->d_name;
867 ret = true;
868 break;
869 }
870 }
871 closedir(devDir);
872
873 return ret;
874 }
875
LookupHidDriverName(std::string & deviceName,std::string & driverName)876 bool HIDDevice::LookupHidDriverName(std::string &deviceName, std::string &driverName)
877 {
878 bool ret = false;
879 ssize_t sz;
880 char link[PATH_MAX];
881 std::string driverLink = "/sys/bus/hid/devices/" + deviceName + "/driver";
882
883 sz = readlink(driverLink.c_str(), link, PATH_MAX);
884 if (sz == -1)
885 return ret;
886
887 link[sz] = 0;
888
889 driverName = std::string(StripPath(link, PATH_MAX));
890
891 return true;
892 }
893
WaitForHidRawDevice(int notifyFd,std::string & hidrawFile)894 bool HIDDevice::WaitForHidRawDevice(int notifyFd, std::string & hidrawFile)
895 {
896 struct timeval timeout;
897 fd_set fds;
898 int rc;
899 ssize_t eventBytesRead;
900 int eventBytesAvailable;
901 size_t sz;
902 char link[PATH_MAX];
903 std::string transportDeviceName;
904 std::string driverPath;
905 std::string hidDeviceName;
906 int offset = 0;
907
908 for (;;) {
909 FD_ZERO(&fds);
910 FD_SET(notifyFd, &fds);
911
912 timeout.tv_sec = 20;
913 timeout.tv_usec = 0;
914
915 rc = select(notifyFd + 1, &fds, NULL, NULL, &timeout);
916 if (rc < 0) {
917 if (errno == -EINTR)
918 continue;
919
920 return false;
921 }
922
923 if (rc == 0) {
924 return false;
925 }
926
927 if (FD_ISSET(notifyFd, &fds)) {
928 struct inotify_event * event;
929
930 rc = ioctl(notifyFd, FIONREAD, &eventBytesAvailable);
931 if (rc < 0) {
932 continue;
933 }
934
935 char buf[eventBytesAvailable];
936
937 eventBytesRead = read(notifyFd, buf, eventBytesAvailable);
938 if (eventBytesRead < 0) {
939 continue;
940 }
941
942 while (offset < eventBytesRead) {
943 event = (struct inotify_event *)&buf[offset];
944
945 if (!strncmp(event->name, "hidraw", 6)) {
946 std::string classPath = std::string("/sys/class/hidraw/")
947 + event->name + "/device";
948 sz = readlink(classPath.c_str(), link, PATH_MAX);
949 link[sz] = 0;
950
951 hidDeviceName = std::string(link).substr(9, 19);
952
953 if (!FindTransportDevice(m_info.bustype, hidDeviceName, transportDeviceName, driverPath)) {
954 fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str());
955 continue;
956 }
957
958 if (transportDeviceName == m_transportDeviceName) {
959 hidrawFile = std::string("/dev/") + event->name;
960 return true;
961 }
962 }
963
964 offset += sizeof(struct inotify_event) + event->len;
965 }
966 }
967 }
968 }
969
FindDevice(enum RMIDeviceType type)970 bool HIDDevice::FindDevice(enum RMIDeviceType type)
971 {
972 DIR * devDir;
973 struct dirent * devDirEntry;
974 char deviceFile[PATH_MAX];
975 bool found = false;
976 int rc;
977 devDir = opendir("/dev");
978 if (!devDir)
979 return -1;
980
981 while ((devDirEntry = readdir(devDir)) != NULL) {
982 if (strstr(devDirEntry->d_name, "hidraw")) {
983 snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name);
984 fprintf(stdout, "Got device : /dev/%s\n", devDirEntry->d_name);
985 rc = Open(deviceFile);
986 if (rc != 0) {
987 continue;
988 } else if (type != RMI_DEVICE_TYPE_ANY && GetDeviceType() != type) {
989 Close();
990 continue;
991 } else {
992 found = true;
993 break;
994 }
995 }
996 }
997 closedir(devDir);
998
999 return found;
1000 }
1001