diff options
Diffstat (limited to 'rmidevice')
-rw-r--r-- | rmidevice/Makefile | 1 | ||||
-rwxr-xr-x | rmidevice/hiddevice.cpp | 170 | ||||
-rwxr-xr-x | rmidevice/hiddevice.h | 7 | ||||
-rw-r--r-- | rmidevice/rmidevice.cpp | 3 | ||||
-rw-r--r-- | rmidevice/rmidevice.h | 6 |
5 files changed, 149 insertions, 38 deletions
diff --git a/rmidevice/Makefile b/rmidevice/Makefile index d9f32cc..4ce6b39 100644 --- a/rmidevice/Makefile +++ b/rmidevice/Makefile @@ -2,6 +2,7 @@ CXX ?= g++ AR ?= ar RANLIB ?= ranlib CPPFLAGS += -I../include -I./include +CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE CXXFLAGS += -fPIC -Wall RMIDEVICESRC = rmifunction.cpp rmidevice.cpp hiddevice.cpp util.cpp RMIDEVICEOBJ = $(RMIDEVICESRC:.cpp=.o) diff --git a/rmidevice/hiddevice.cpp b/rmidevice/hiddevice.cpp index 709559d..4cedc5a 100755 --- a/rmidevice/hiddevice.cpp +++ b/rmidevice/hiddevice.cpp @@ -40,14 +40,22 @@ #define RMI_READ_DATA_REPORT_ID 0xb // Input Report #define RMI_ATTN_REPORT_ID 0xc // Input Report #define RMI_SET_RMI_MODE_REPORT_ID 0xf // Feature Report +#define RMI_SET_LID_MODE_REPORT_ID 0xe // Feature Report -enum hid_report_type { - HID_REPORT_TYPE_UNKNOWN = 0x0, - HID_REPORT_TYPE_INPUT = 0x81, - HID_REPORT_TYPE_OUTPUT = 0x91, - HID_REPORT_TYPE_FEATURE = 0xb1, + +// Make sure that none of the enums/macros conflict with possible +// kernel definition/names. +enum hid_rmi4_report_type { + HID_RMI4_REPORT_UNKNOWN = 0, + HID_RMI4_REPORT_INPUT = 1, + HID_RMI4_REPORT_OUTPUT = 2, + HID_RMI4_REPORT_FEATURE = 3, }; +#define HID_RMI4_REPORT_TYPE_INPUT 0x81 +#define HID_RMI4_REPORT_TYPE_OUTPUT 0x91 +#define HID_RMI4_REPORT_TYPE_FEATURE 0xb1 + #define HID_RMI4_REPORT_ID 0 #define HID_RMI4_READ_INPUT_COUNT 1 #define HID_RMI4_READ_INPUT_DATA 2 @@ -161,7 +169,7 @@ void HIDDevice::ParseReportDescriptor() int totalReportSize = 0; int reportSize = 0; int reportCount = 0; - enum hid_report_type hidReportType = HID_REPORT_TYPE_UNKNOWN; + enum hid_rmi4_report_type hidReportType = HID_RMI4_REPORT_UNKNOWN; bool inCollection = false; for (unsigned int i = 0; i < m_rptDesc.size; ++i) { @@ -179,16 +187,16 @@ void HIDDevice::ParseReportDescriptor() totalReportSize = (reportSize * reportCount) >> 3; switch (hidReportType) { - case HID_REPORT_TYPE_INPUT: + case HID_RMI4_REPORT_INPUT: m_inputReportSize = totalReportSize + 1; break; - case HID_REPORT_TYPE_OUTPUT: + case HID_RMI4_REPORT_OUTPUT: m_outputReportSize = totalReportSize + 1; break; - case HID_REPORT_TYPE_FEATURE: + case HID_RMI4_REPORT_FEATURE: m_featureReportSize = totalReportSize + 1; break; - case HID_REPORT_TYPE_UNKNOWN: + case HID_RMI4_REPORT_UNKNOWN: default: break; } @@ -198,7 +206,7 @@ void HIDDevice::ParseReportDescriptor() totalReportSize = 0; reportSize = 0; reportCount = 0; - hidReportType = HID_REPORT_TYPE_UNKNOWN; + hidReportType = HID_RMI4_REPORT_UNKNOWN; isReport = true; } @@ -218,14 +226,18 @@ void HIDDevice::ParseReportDescriptor() continue; } - if (m_rptDesc.value[i] == HID_REPORT_TYPE_INPUT) - hidReportType = HID_REPORT_TYPE_INPUT; + if (m_rptDesc.value[i] == RMI_SET_LID_MODE_REPORT_ID) { + hasVendorDefineLIDMode = true; + } + + if (m_rptDesc.value[i] == HID_RMI4_REPORT_TYPE_INPUT) + hidReportType = HID_RMI4_REPORT_INPUT; - if (m_rptDesc.value[i] == HID_REPORT_TYPE_OUTPUT) - hidReportType = HID_REPORT_TYPE_OUTPUT; + if (m_rptDesc.value[i] == HID_RMI4_REPORT_TYPE_OUTPUT) + hidReportType = HID_RMI4_REPORT_OUTPUT; - if (m_rptDesc.value[i] == HID_REPORT_TYPE_FEATURE) { - hidReportType = HID_REPORT_TYPE_FEATURE; + if (m_rptDesc.value[i] == HID_RMI4_REPORT_TYPE_FEATURE) { + hidReportType = HID_RMI4_REPORT_FEATURE; } } } @@ -291,16 +303,32 @@ int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len) size_t bytesToRequest; int reportId; int rc; + struct timeval tv; + int resendCount = 0; + tv.tv_sec = 10 / 1000; + tv.tv_usec = (10 % 1000) * 1000; + if (!m_deviceOpen) return -1; + if (m_hasDebug) { + fprintf(stdout, "R %02x : ", addr); + } + if (m_bytesPerReadRequest) bytesPerRequest = m_bytesPerReadRequest; else bytesPerRequest = len; for (totalBytesRead = 0; totalBytesRead < len; totalBytesRead += bytesReadPerRequest) { +Resend: + if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) { + if (resendCount == 3) { + fprintf(stderr, "resend count exceed, return as failure\n"); + return -1; + } + } count = 0; if ((len - totalBytesRead) < bytesPerRequest) bytesToRequest = len % bytesPerRequest; @@ -334,7 +362,13 @@ int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len) bytesReadPerRequest = 0; while (bytesReadPerRequest < bytesToRequest) { - rc = GetReport(&reportId); + if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) { + // Add timeout 10 ms for select() called in GetReport(). + rc = GetReport(&reportId, &tv); + } else { + // Touch Screen + rc = GetReport(&reportId); + } if (rc > 0 && reportId == RMI_READ_DATA_REPORT_ID) { if (static_cast<ssize_t>(m_inputReportSize) < std::max(HID_RMI4_READ_INPUT_COUNT, @@ -350,10 +384,24 @@ int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len) bytesInDataReport); bytesReadPerRequest += bytesInDataReport; m_dataBytesRead = 0; + if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) { + // Resend sheme is supported on TP only. + resendCount = 0; + } + } else if (GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) { + fprintf(stderr, "Some error with GetReport : rc(%d), reportID(0x%x)\n", rc, reportId); + resendCount += 1; + goto Resend; } } addr += bytesPerRequest; } + if (m_hasDebug) { + for (int i=0 ; i<len ; i++) { + fprintf(stdout, "%02x ", buf[i]); + } + fprintf(stdout, "\n"); + } return totalBytesRead; } @@ -374,6 +422,14 @@ int HIDDevice::Write(unsigned short addr, const unsigned char *buf, unsigned sho m_outputReport[HID_RMI4_WRITE_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF; memcpy(&m_outputReport[HID_RMI4_WRITE_OUTPUT_DATA], buf, len); + if (m_hasDebug) { + fprintf(stdout, "W %02x : ", addr); + for (int i=0 ; i<len ; i++) { + fprintf(stdout, "%02x ", buf[i]); + } + fprintf(stdout, "\n"); + } + for (;;) { m_bCancel = false; count = write(m_fd, m_outputReport, m_outputReportSize); @@ -391,11 +447,11 @@ int HIDDevice::SetMode(int mode) { int rc; char buf[2]; - + if (!m_deviceOpen) return -1; - buf[0] = 0xF; + buf[0] = RMI_SET_RMI_MODE_REPORT_ID; buf[1] = mode; rc = ioctl(m_fd, HIDIOCSFEATURE(2), buf); if (rc < 0) { @@ -406,6 +462,44 @@ int HIDDevice::SetMode(int mode) return 0; } +int HIDDevice::ToggleInterruptMask(bool enable) +{ + int rc; + char buf[2]; + + if (GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) { + fprintf(stdout, "Not TP, skip toggle interrupts mask\n"); + return 0; + } + + // We can have information to see whether it exists this feature report currentlt. + // However, it might have no action even we set this feature with specific value. + // Need FW team's help to query more information about the existence of functions. + if (!hasVendorDefineLIDMode) { + if (m_hasDebug) { + fprintf(stdout, "no LID mode feature, return\n"); + } + return 0; + } + + if (!m_deviceOpen) + return -1; + + buf[0] = RMI_SET_LID_MODE_REPORT_ID; + if (enable) { + buf[1] = 0; + } else { + buf[1] = 8; + } + rc = ioctl(m_fd, HIDIOCSFEATURE(2), buf); + if (rc < 0) { + perror("HIDIOCSFEATURE"); + return rc; + } + Sleep(10); + return 0; +} + void HIDDevice::Close() { RMIDevice::Close(); @@ -655,11 +749,9 @@ bool HIDDevice::CheckABSEvent() int fd=-1; unsigned int type; int abs[6] = {0}; - int k; struct dirent **namelist; - int i, ndev, devnum, match; - char *filename; - int max_device = 0; + int i, ndev; + char input_event_name[PATH_MAX]; unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; @@ -793,15 +885,8 @@ bool HIDDevice::FindTransportDevice(uint32_t bus, std::string & hidDeviceName, if (bus == BUS_I2C) { devicePrefix += "i2c/"; - // From new patch released on 2020/11, i2c_hid would be renamed as i2c_hid_acpi, - // and also need backward compatible. - std::string driverPathTemp = devicePrefix + "drivers/i2c_hid/"; - DIR *driverPathtest = opendir(driverPathTemp.c_str()); - if(!driverPathtest) { - driverPath = devicePrefix + "drivers/i2c_hid_acpi/"; - } else { - driverPath = devicePrefix + "drivers/i2c_hid/"; - } + // The i2c driver module installed on system is vary (i2c_hid, i2c_hid_acpi, i2c_hid_of), + // so we will assign driver path until we get device name later. } else { devicePrefix += "usb/"; driverPath = devicePrefix + "drivers/usbhid/"; @@ -840,8 +925,25 @@ bool HIDDevice::FindTransportDevice(uint32_t bus, std::string & hidDeviceName, } closedir(devDir); - if (deviceFound) + if (deviceFound) { + if (bus == BUS_I2C) { + std::fstream ueventfile; + std::string ueventfilepath = fullLinkPath + "/uevent"; + std::string uevent; + std::string modulename; + ueventfile.open(ueventfilepath.c_str(), std::ios::in); + if(ueventfile.is_open()) { + getline(ueventfile, uevent); + modulename = uevent.substr(uevent.find("=") + 1, std::string::npos); + driverPath = devicePrefix + "drivers/"; + driverPath += modulename; + driverPath += "/"; + } + ueventfile.close(); + } break; + } + } closedir(devicesDir); diff --git a/rmidevice/hiddevice.h b/rmidevice/hiddevice.h index b947f62..93b1ed8 100755 --- a/rmidevice/hiddevice.h +++ b/rmidevice/hiddevice.h @@ -20,6 +20,7 @@ #include <linux/hidraw.h> #include <string> +#include <fstream> #include <stdint.h> #include "rmidevice.h" @@ -41,7 +42,8 @@ public: m_mode(HID_RMI4_MODE_ATTN_REPORTS), m_initialMode(HID_RMI4_MODE_MOUSE), m_transportDeviceName(""), - m_driverPath("") + m_driverPath(""), + hasVendorDefineLIDMode(false) {} virtual int Open(const char * filename); virtual int Read(unsigned short addr, unsigned char *buf, @@ -49,6 +51,7 @@ public: virtual int Write(unsigned short addr, const unsigned char *buf, unsigned short len); virtual int SetMode(int mode); + virtual int ToggleInterruptMask(bool enable); virtual int WaitForAttention(struct timeval * timeout = NULL, unsigned int source_mask = RMI_INTERUPT_SOURCES_ALL_MASK); virtual int GetAttentionReport(struct timeval * timeout, unsigned int source_mask, @@ -87,6 +90,8 @@ private: std::string m_transportDeviceName; std::string m_driverPath; + bool hasVendorDefineLIDMode; + int GetReport(int *reportId, struct timeval * timeout = NULL); void PrintReport(const unsigned char *report); void ParseReportDescriptor(); diff --git a/rmidevice/rmidevice.cpp b/rmidevice/rmidevice.cpp index 15335f9..029e614 100644 --- a/rmidevice/rmidevice.cpp +++ b/rmidevice/rmidevice.cpp @@ -62,7 +62,6 @@ int RMIDevice::SetRMIPage(unsigned char page) if (m_page == page) return 0; - m_page = page; rc = Write(RMI_DEVICE_PAGE_SELECT_REGISTER, &page, 1); if (rc < 0 || rc < 1) { @@ -327,7 +326,7 @@ int RMIDevice::ScanPDT(int endFunc, int endPage) } m_numInterruptRegs = (interruptCount + 7) / 8; - + return 0; } diff --git a/rmidevice/rmidevice.h b/rmidevice/rmidevice.h index 9bfe849..9b8c915 100644 --- a/rmidevice/rmidevice.h +++ b/rmidevice/rmidevice.h @@ -38,7 +38,7 @@ class RMIDevice public: RMIDevice() : m_functionList(), m_sensorID(0), m_bCancel(false), m_bytesPerReadRequest(0), m_page(-1), m_deviceType(RMI_DEVICE_TYPE_ANY) - {} + { m_hasDebug = false; } virtual ~RMIDevice() {} virtual int Open(const char * filename) = 0; virtual int Read(unsigned short addr, unsigned char *data, @@ -46,6 +46,7 @@ public: virtual int Write(unsigned short addr, const unsigned char *data, unsigned short len) = 0; virtual int SetMode(int mode) { return -1; /* Unsupported */ } + virtual int ToggleInterruptMask(bool enable) = 0; virtual int WaitForAttention(struct timeval * timeout = NULL, unsigned int source_mask = RMI_INTERUPT_SOURCES_ALL_MASK) = 0; virtual int GetAttentionReport(struct timeval * timeout, unsigned int source_mask, @@ -61,6 +62,7 @@ public: int GetFirmwareVersionMajor() { return m_firmwareVersionMajor; } int GetFirmwareVersionMinor() { return m_firmwareVersionMinor; } virtual int QueryBasicProperties(); + char *GetProductID() { return (char *)m_productID; } int SetRMIPage(unsigned char page); @@ -81,6 +83,8 @@ public: virtual bool FindDevice(enum RMIDeviceType type = RMI_DEVICE_TYPE_ANY) = 0; enum RMIDeviceType GetDeviceType() { return m_deviceType; } + bool m_hasDebug; + protected: std::vector<RMIFunction> m_functionList; unsigned char m_manufacturerID; |