• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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