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