From b834379cfd2082e895dad101e3784f55c6fdf517 Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Mon, 30 Jul 2018 15:38:46 -0700 Subject: Cache the transport device and use that when rebinding the driver and read all pending inotifyt events --- rmidevice/hiddevice.cpp | 87 ++++++++++++++++++++++++++++++------------------- rmidevice/hiddevice.h | 10 ++++-- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/rmidevice/hiddevice.cpp b/rmidevice/hiddevice.cpp index 18b957e..c739412 100644 --- a/rmidevice/hiddevice.cpp +++ b/rmidevice/hiddevice.cpp @@ -629,8 +629,6 @@ void HIDDevice::RebindDriver() int vendor = m_info.vendor; int product = m_info.product; std::string hidDeviceName; - std::string transportDeviceName; - std::string driverPath; std::string bindFile; std::string unbindFile; std::string hidrawFile; @@ -652,33 +650,36 @@ void HIDDevice::RebindDriver() return; } - if (!LookupHidDeviceName(bus, vendor, product, hidDeviceName)) { - fprintf(stderr, "Failed to find HID device name for the specified device: bus (0x%x) vendor: (0x%x) product: (0x%x)\n", - bus, vendor, product); - return; - } + if (m_transportDeviceName == "") { + if (!LookupHidDeviceName(bus, vendor, product, hidDeviceName)) { + fprintf(stderr, "Failed to find HID device name for the specified device: bus (0x%x) vendor: (0x%x) product: (0x%x)\n", + bus, vendor, product); + return; + } + + if (!FindTransportDevice(bus, hidDeviceName, m_transportDeviceName, m_driverPath)) { + fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str()); + return; + } - if (!FindTransportDevice(bus, hidDeviceName, transportDeviceName, driverPath)) { - fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str()); - return; } - bindFile = driverPath + "bind"; - unbindFile = driverPath + "unbind"; + bindFile = m_driverPath + "bind"; + unbindFile = m_driverPath + "unbind"; - if (!WriteDeviceNameToFile(unbindFile.c_str(), transportDeviceName.c_str())) { + if (!WriteDeviceNameToFile(unbindFile.c_str(), m_transportDeviceName.c_str())) { fprintf(stderr, "Failed to unbind HID device %s: %s\n", - transportDeviceName.c_str(), strerror(errno)); + m_transportDeviceName.c_str(), strerror(errno)); return; } - if (!WriteDeviceNameToFile(bindFile.c_str(), transportDeviceName.c_str())) { + if (!WriteDeviceNameToFile(bindFile.c_str(), m_transportDeviceName.c_str())) { fprintf(stderr, "Failed to bind HID device %s: %s\n", - transportDeviceName.c_str(), strerror(errno)); + m_transportDeviceName.c_str(), strerror(errno)); return; } - if (WaitForHidRawDevice(notifyFd, hidDeviceName, hidrawFile)) { + if (WaitForHidRawDevice(notifyFd, hidrawFile)) { rc = Open(hidrawFile.c_str()); if (rc) fprintf(stderr, "Failed to open device (%s) during rebind: %d: errno: %s (%d)\n", @@ -790,14 +791,19 @@ bool HIDDevice::LookupHidDriverName(std::string &deviceName, std::string &driver return true; } -bool HIDDevice::WaitForHidRawDevice(int notifyFd, std::string & deviceName, - std::string & hidrawFile) +bool HIDDevice::WaitForHidRawDevice(int notifyFd, std::string & hidrawFile) { struct timeval timeout; fd_set fds; int rc; + ssize_t eventBytesRead; + int eventBytesAvailable; size_t sz; char link[PATH_MAX]; + std::string transportDeviceName; + std::string driverPath; + std::string hidDeviceName; + int offset = 0; for (;;) { FD_ZERO(&fds); @@ -820,29 +826,42 @@ bool HIDDevice::WaitForHidRawDevice(int notifyFd, std::string & deviceName, if (FD_ISSET(notifyFd, &fds)) { struct inotify_event * event; - const int buf_len = sizeof(struct inotify_event) + NAME_MAX + 1; - char buf[buf_len]; - rc = read(notifyFd, buf, buf_len); + rc = ioctl(notifyFd, FIONREAD, &eventBytesAvailable); if (rc < 0) { continue; } - event = (struct inotify_event *)buf; + char buf[eventBytesAvailable]; + + eventBytesRead = read(notifyFd, buf, eventBytesAvailable); + if (eventBytesRead < 0) { + continue; + } + + while (offset < eventBytesRead) { + event = (struct inotify_event *)&buf[offset]; + + if (!strncmp(event->name, "hidraw", 6)) { + std::string classPath = std::string("/sys/class/hidraw/") + + event->name + "/device"; + sz = readlink(classPath.c_str(), link, PATH_MAX); + link[sz] = 0; - if (!strncmp(event->name, "hidraw", 6)) { - std::string classPath = std::string("/sys/class/hidraw/") - + event->name + "/device"; - sz = readlink(classPath.c_str(), link, PATH_MAX); - link[sz] = 0; + hidDeviceName = std::string(link).substr(9, 19); - // The buffer looks something like ../../../0018:06CB:76AD.0014 - // Add 9 to strip off ../../../ and ignore the id on the end which - // changes per instance. - if (!strncmp(deviceName.c_str(), link + 9, 14)) { - hidrawFile = std::string("/dev/") + event->name; - return true; + if (!FindTransportDevice(m_info.bustype, hidDeviceName, transportDeviceName, driverPath)) { + fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str()); + continue; + } + + if (transportDeviceName == m_transportDeviceName) { + hidrawFile = std::string("/dev/") + event->name; + return true; + } } + + offset += sizeof(struct inotify_event) + event->len; } } } diff --git a/rmidevice/hiddevice.h b/rmidevice/hiddevice.h index 3cb314a..d5dfec1 100644 --- a/rmidevice/hiddevice.h +++ b/rmidevice/hiddevice.h @@ -39,7 +39,9 @@ public: m_featureReportSize(0), m_deviceOpen(false), m_mode(HID_RMI4_MODE_ATTN_REPORTS), - m_initialMode(HID_RMI4_MODE_MOUSE) + m_initialMode(HID_RMI4_MODE_MOUSE), + m_transportDeviceName(""), + m_driverPath("") {} virtual int Open(const char * filename); virtual int Read(unsigned short addr, unsigned char *buf, @@ -81,16 +83,20 @@ private: rmi_hid_mode_type m_mode; rmi_hid_mode_type m_initialMode; + std::string m_transportDeviceName; + std::string m_driverPath; + int GetReport(int *reportId, struct timeval * timeout = NULL); void PrintReport(const unsigned char *report); void ParseReportDescriptor(); + bool WaitForHidRawDevice(int notifyFd, std::string & hidraw); + // static HID utility functions static bool LookupHidDeviceName(uint32_t bus, int16_t vendorId, int16_t productId, std::string &deviceName); static bool LookupHidDriverName(std::string &deviceName, std::string &driverName); static bool FindTransportDevice(uint32_t bus, std::string & hidDeviceName, std::string & transportDeviceName, std::string & driverPath); - static bool WaitForHidRawDevice(int notifyFd, std::string & deviceName, std::string & hidraw); }; #endif /* _HIDDEVICE_H_ */ -- cgit v1.2.3