xref: /aosp_15_r20/external/rmi4utils/rmidevice/hiddevice.cpp (revision a248dafd7653b99fc45f9d29e5f139b04f2f28bc)
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