aboutsummaryrefslogtreecommitdiff
path: root/rmidevice
diff options
context:
space:
mode:
Diffstat (limited to 'rmidevice')
-rw-r--r--rmidevice/Android.bp6
-rw-r--r--rmidevice/Makefile2
-rwxr-xr-x[-rw-r--r--]rmidevice/hiddevice.cpp446
-rwxr-xr-x[-rw-r--r--]rmidevice/hiddevice.h36
-rw-r--r--rmidevice/rmidevice.cpp66
-rw-r--r--rmidevice/rmidevice.h24
-rw-r--r--rmidevice/util.cpp70
7 files changed, 503 insertions, 147 deletions
diff --git a/rmidevice/Android.bp b/rmidevice/Android.bp
index 6d67f4c..9b6ec71 100644
--- a/rmidevice/Android.bp
+++ b/rmidevice/Android.bp
@@ -10,14 +10,16 @@ package {
cc_library_static {
name: "rmidevice",
srcs: [
- "rmifunction.cpp",
- "rmidevice.cpp",
"hiddevice.cpp",
+ "rmidevice.cpp",
+ "rmifunction.cpp",
+ "util.cpp",
],
cflags: [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
+ "-Wno-unused-variable",
],
export_include_dirs: ["."],
}
diff --git a/rmidevice/Makefile b/rmidevice/Makefile
index 35aec55..d9f32cc 100644
--- a/rmidevice/Makefile
+++ b/rmidevice/Makefile
@@ -3,7 +3,7 @@ AR ?= ar
RANLIB ?= ranlib
CPPFLAGS += -I../include -I./include
CXXFLAGS += -fPIC -Wall
-RMIDEVICESRC = rmifunction.cpp rmidevice.cpp hiddevice.cpp
+RMIDEVICESRC = rmifunction.cpp rmidevice.cpp hiddevice.cpp util.cpp
RMIDEVICEOBJ = $(RMIDEVICESRC:.cpp=.o)
LIBNAME = librmidevice.so
STATIC_LIBNAME = librmidevice.a
diff --git a/rmidevice/hiddevice.cpp b/rmidevice/hiddevice.cpp
index 7ebf5fd..709559d 100644..100755
--- a/rmidevice/hiddevice.cpp
+++ b/rmidevice/hiddevice.cpp
@@ -31,6 +31,7 @@
#include <linux/hidraw.h>
#include <signal.h>
#include <stdlib.h>
+#include <sys/inotify.h>
#include "hiddevice.h"
@@ -40,12 +41,6 @@
#define RMI_ATTN_REPORT_ID 0xc // Input Report
#define RMI_SET_RMI_MODE_REPORT_ID 0xf // Feature Report
-enum rmi_hid_mode_type {
- HID_RMI4_MODE_MOUSE = 0,
- HID_RMI4_MODE_ATTN_REPORTS = 1,
- HID_RMI4_MODE_NO_PACKED_ATTN_REPORTS = 2,
-};
-
enum hid_report_type {
HID_REPORT_TYPE_UNKNOWN = 0x0,
HID_REPORT_TYPE_INPUT = 0x81,
@@ -71,6 +66,8 @@ int HIDDevice::Open(const char * filename)
{
int rc;
int desc_size;
+ std::string hidDeviceName;
+ std::string hidDriverName;
if (!filename)
return -EINVAL;
@@ -84,58 +81,80 @@ int HIDDevice::Open(const char * filename)
rc = ioctl(m_fd, HIDIOCGRDESCSIZE, &desc_size);
if (rc < 0)
- return rc;
+ goto error;
m_rptDesc.size = desc_size;
rc = ioctl(m_fd, HIDIOCGRDESC, &m_rptDesc);
if (rc < 0)
- return rc;
+ goto error;
rc = ioctl(m_fd, HIDIOCGRAWINFO, &m_info);
if (rc < 0)
- return rc;
+ goto error;
if (m_info.vendor != SYNAPTICS_VENDOR_ID) {
errno = -ENODEV;
- return -1;
+ rc = -1;
+ goto error;
}
- ParseReportSizes();
+ ParseReportDescriptor();
m_inputReport = new unsigned char[m_inputReportSize]();
if (!m_inputReport) {
errno = -ENOMEM;
- return -1;
+ rc = -1;
+ goto error;
}
m_outputReport = new unsigned char[m_outputReportSize]();
if (!m_outputReport) {
errno = -ENOMEM;
- return -1;
+ rc = -1;
+ goto error;
}
m_readData = new unsigned char[m_inputReportSize]();
if (!m_readData) {
errno = -ENOMEM;
- return -1;
+ rc = -1;
+ goto error;
}
m_attnData = new unsigned char[m_inputReportSize]();
if (!m_attnData) {
errno = -ENOMEM;
- return -1;
+ rc = -1;
+ goto error;
}
m_deviceOpen = true;
- rc = SetMode(HID_RMI4_MODE_ATTN_REPORTS);
- if (rc)
- return -1;
+ // Determine which mode the device is currently running in based on the current HID driver
+ // hid-rmi indicated RMI Mode 1 all others would be Mode 0
+ if (LookupHidDeviceName(m_info.bustype, m_info.vendor, m_info.product, hidDeviceName)) {
+ if (LookupHidDriverName(hidDeviceName, hidDriverName)) {
+ if (hidDriverName == "hid-rmi")
+ m_initialMode = HID_RMI4_MODE_ATTN_REPORTS;
+ }
+ }
+
+ if (m_initialMode != m_mode) {
+ rc = SetMode(m_mode);
+ if (rc) {
+ rc = -1;
+ goto error;
+ }
+ }
return 0;
+
+error:
+ Close();
+ return rc;
}
-void HIDDevice::ParseReportSizes()
+void HIDDevice::ParseReportDescriptor()
{
bool isVendorSpecific = false;
bool isReport = false;
@@ -143,10 +162,18 @@ void HIDDevice::ParseReportSizes()
int reportSize = 0;
int reportCount = 0;
enum hid_report_type hidReportType = HID_REPORT_TYPE_UNKNOWN;
+ bool inCollection = false;
for (unsigned int i = 0; i < m_rptDesc.size; ++i) {
+ if (m_rptDesc.value[i] == 0xc0) {
+ inCollection = false;
+ isVendorSpecific = false;
+ isReport = false;
+ continue;
+ }
+
if (isVendorSpecific) {
- if (m_rptDesc.value[i] == 0x85 || m_rptDesc.value[i] == 0xc0) {
+ if (m_rptDesc.value[i] == 0x85) {
if (isReport) {
// finish up data on the previous report
totalReportSize = (reportSize * reportCount) >> 3;
@@ -173,13 +200,7 @@ void HIDDevice::ParseReportSizes()
reportCount = 0;
hidReportType = HID_REPORT_TYPE_UNKNOWN;
- if (m_rptDesc.value[i] == 0x85)
- isReport = true;
- else
- isReport = false;
-
- if (m_rptDesc.value[i] == 0xc0)
- isVendorSpecific = false;
+ isReport = true;
}
if (isReport) {
@@ -209,12 +230,52 @@ void HIDDevice::ParseReportSizes()
}
}
- if (i + 2 >= m_rptDesc.size)
- return;
- if (m_rptDesc.value[i] == 0x06 && m_rptDesc.value[i + 1] == 0x00
- && m_rptDesc.value[i + 2] == 0xFF) {
- isVendorSpecific = true;
- i += 2;
+ if (!inCollection) {
+ switch (m_rptDesc.value[i]) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ inCollection = true;
+ break;
+ case 0x05:
+ inCollection = true;
+
+ if (i + 3 >= m_rptDesc.size)
+ break;
+
+ // touchscreens with active pen have a Generic Mouse collection
+ // so stop searching if we have already found the touchscreen digitizer
+ // usage.
+ if (m_deviceType == RMI_DEVICE_TYPE_TOUCHSCREEN)
+ break;
+
+ if (m_rptDesc.value[i + 1] == 0x01) {
+ if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x02)
+ m_deviceType = RMI_DEVICE_TYPE_TOUCHPAD;
+ } else if (m_rptDesc.value[i + 1] == 0x0d) {
+ if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x04)
+ m_deviceType = RMI_DEVICE_TYPE_TOUCHSCREEN;
+ // for Precision Touch Pad
+ else if (m_rptDesc.value[i + 2] == 0x09 && m_rptDesc.value[i + 3] == 0x05)
+ m_deviceType = RMI_DEVICE_TYPE_TOUCHPAD;
+ }
+ i += 3;
+ break;
+ case 0x06:
+ inCollection = true;
+ if (i + 2 >= m_rptDesc.size)
+ break;
+
+ if (m_rptDesc.value[i + 1] == 0x00 && m_rptDesc.value[i + 2] == 0xFF)
+ isVendorSpecific = true;
+ i += 2;
+ break;
+ default:
+ break;
+
+ }
}
}
}
@@ -277,12 +338,14 @@ int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len)
if (rc > 0 && reportId == RMI_READ_DATA_REPORT_ID) {
if (static_cast<ssize_t>(m_inputReportSize) <
std::max(HID_RMI4_READ_INPUT_COUNT,
- HID_RMI4_READ_INPUT_DATA))
+ HID_RMI4_READ_INPUT_DATA)){
return -1;
+ }
bytesInDataReport = m_readData[HID_RMI4_READ_INPUT_COUNT];
if (bytesInDataReport > bytesToRequest
- || bytesReadPerRequest + bytesInDataReport > len)
+ || bytesReadPerRequest + bytesInDataReport > len){
return -1;
+ }
memcpy(buf + bytesReadPerRequest, &m_readData[HID_RMI4_READ_INPUT_DATA],
bytesInDataReport);
bytesReadPerRequest += bytesInDataReport;
@@ -345,10 +408,14 @@ int HIDDevice::SetMode(int mode)
void HIDDevice::Close()
{
+ RMIDevice::Close();
+
if (!m_deviceOpen)
return;
- SetMode(HID_RMI4_MODE_MOUSE);
+ if (m_initialMode != m_mode)
+ SetMode(m_initialMode);
+
m_deviceOpen = false;
close(m_fd);
m_fd = -1;
@@ -527,10 +594,15 @@ void HIDDevice::PrintReport(const unsigned char *report)
// Print protocol specific device information
void HIDDevice::PrintDeviceInfo()
{
+ enum RMIDeviceType deviceType = GetDeviceType();
+
fprintf(stdout, "HID device info:\nBus: %s Vendor: 0x%04x Product: 0x%04x\n",
m_info.bustype == BUS_I2C ? "I2C" : "USB", m_info.vendor, m_info.product);
fprintf(stdout, "Report sizes: input: %ld output: %ld\n", (unsigned long)m_inputReportSize,
(unsigned long)m_outputReportSize);
+ if (deviceType)
+ fprintf(stdout, "device type: %s\n", deviceType == RMI_DEVICE_TYPE_TOUCHSCREEN ?
+ "touchscreen" : "touchpad");
}
bool WriteDeviceNameToFile(const char * file, const char * str)
@@ -555,76 +627,159 @@ bool WriteDeviceNameToFile(const char * file, const char * str)
return close(fd) == 0 && size == static_cast<ssize_t>(strlen(str));
}
+static const char * const absval[6] = { "Value", "Min ", "Max ", "Fuzz ", "Flat ", "Resolution "};
+#define KEY_MAX 0x2ff
+#define EV_MAX 0x1f
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define BIT(x) (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
+#define DEV_INPUT_EVENT "/dev/input"
+#define EVENT_DEV_NAME "event"
+/**
+ * Filter for the AutoDevProbe scandir on /dev/input.
+ *
+ * @param dir The current directory entry provided by scandir.
+ *
+ * @return Non-zero if the given directory entry starts with "event", or zero
+ * otherwise.
+ */
+static int is_event_device(const struct dirent *dir) {
+ return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
+}
+
+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;
+ char input_event_name[PATH_MAX];
+ unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
+
+
+#ifdef __BIONIC__
+ // Android's libc doesn't have the GNU versionsort extension.
+ ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, alphasort);
+#else
+ ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, versionsort);
+#endif
+ if (ndev <= 0)
+ return false;
+ for (i = 0; i < ndev; i++)
+ {
+ char fname[64];
+ int fd = -1;
+ char name[256] = "???";
+
+ snprintf(fname, sizeof(fname),
+ "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
+ fd = open(fname, O_RDONLY);
+ if (fd < 0)
+ continue;
+ ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+ //fprintf(stderr, "%s: %s\n", fname, name);
+ close(fd);
+ if(strstr(name, m_transportDeviceName.c_str()+4))
+ {
+ snprintf(input_event_name, sizeof(fname), "%s", fname);
+ }
+ free(namelist[i]);
+ }
+
+ if ((fd = open(input_event_name, O_RDONLY)) < 0) {
+ if (errno == EACCES && getuid() != 0)
+ fprintf(stderr, "No access right \n");
+ }
+ memset(bit, 0, sizeof(bit));
+ ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
+ for (type = 0; type < EV_MAX; type++) {
+ if (test_bit(type, bit[0]) && type == EV_ABS) {
+ ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit[type]);
+ if (test_bit(ABS_X, bit[type])) {
+ ioctl(fd, EVIOCGABS(ABS_X), abs);
+ if(abs[2] == 0) //maximum
+ {
+ Sleep(1000);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
void HIDDevice::RebindDriver()
{
int bus = m_info.bustype;
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;
- struct stat stat_buf;
+ int notifyFd;
+ int wd;
int rc;
- int i;
-
Close();
- 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);
+ notifyFd = inotify_init();
+ if (notifyFd < 0) {
+ fprintf(stderr, "Failed to initialize inotify\n");
return;
}
- if (!FindTransportDevice(bus, hidDeviceName, transportDeviceName, driverPath)) {
- fprintf(stderr, "Failed to find the transport device / driver for %s\n", hidDeviceName.c_str());
+ wd = inotify_add_watch(notifyFd, "/dev", IN_CREATE);
+ if (wd < 0) {
+ fprintf(stderr, "Failed to add watcher for /dev\n");
return;
}
- bindFile = driverPath + "bind";
- unbindFile = driverPath + "unbind";
+ 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 (!WriteDeviceNameToFile(unbindFile.c_str(), transportDeviceName.c_str())) {
- fprintf(stderr, "Failed to unbind HID device %s: %s\n",
- transportDeviceName.c_str(), strerror(errno));
- 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 (!WriteDeviceNameToFile(bindFile.c_str(), transportDeviceName.c_str())) {
- fprintf(stderr, "Failed to bind HID device %s: %s\n",
- transportDeviceName.c_str(), strerror(errno));
- return;
}
+
+ bindFile = m_driverPath + "bind";
+ unbindFile = m_driverPath + "unbind";
- // The hid device id has changed since this is now a new hid device. Now we have to look up the new name.
- 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);
+ Sleep(500);
+ if (!WriteDeviceNameToFile(unbindFile.c_str(), m_transportDeviceName.c_str())) {
+ fprintf(stderr, "Failed to unbind HID device %s: %s\n",
+ m_transportDeviceName.c_str(), strerror(errno));
return;
}
-
- if (!FindHidRawFile(hidDeviceName, hidrawFile)) {
- fprintf(stderr, "Failed to find the hidraw device file for %s\n", hidDeviceName.c_str());
+ Sleep(500);
+ if (!WriteDeviceNameToFile(bindFile.c_str(), m_transportDeviceName.c_str())) {
+ fprintf(stderr, "Failed to bind HID device %s: %s\n",
+ m_transportDeviceName.c_str(), strerror(errno));
return;
}
- for (i = 0; i < 200; i++) {
- rc = stat(hidrawFile.c_str(), &stat_buf);
- if (!rc)
- break;
- Sleep(5);
+ 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",
+ hidrawFile.c_str(), rc, strerror(errno), errno);
}
-
- rc = Open(hidrawFile.c_str());
- if (rc)
- fprintf(stderr, "Failed to open device (%s) during rebind: %d: errno: %s (%d)\n",
- hidrawFile.c_str(), rc, strerror(errno), errno);
}
-bool HIDDevice::FindTransportDevice(int bus, std::string & hidDeviceName,
+bool HIDDevice::FindTransportDevice(uint32_t bus, std::string & hidDeviceName,
std::string & transportDeviceName, std::string & driverPath)
{
std::string devicePrefix = "/sys/bus/";
@@ -638,7 +793,15 @@ bool HIDDevice::FindTransportDevice(int bus, std::string & hidDeviceName,
if (bus == BUS_I2C) {
devicePrefix += "i2c/";
- driverPath = devicePrefix + "drivers/i2c_hid/";
+ // 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/";
+ }
} else {
devicePrefix += "usb/";
driverPath = devicePrefix + "drivers/usbhid/";
@@ -685,14 +848,14 @@ bool HIDDevice::FindTransportDevice(int bus, std::string & hidDeviceName,
return deviceFound;
}
-bool HIDDevice::LookupHidDeviceName(int bus, int vendorId, int productId, std::string & deviceName)
+bool HIDDevice::LookupHidDeviceName(uint32_t bus, int16_t vendorId, int16_t productId, std::string & deviceName)
{
bool ret = false;
struct dirent * devDirEntry;
DIR * devDir;
char devicePrefix[15];
- snprintf(devicePrefix, 15, "%04X:%04X:%04X", bus, vendorId, productId);
+ snprintf(devicePrefix, 15, "%04X:%04X:%04X", bus, (vendorId & 0xFFFF), (productId & 0xFFFF));
devDir = opendir("/sys/bus/hid/devices");
if (!devDir)
@@ -710,27 +873,128 @@ bool HIDDevice::LookupHidDeviceName(int bus, int vendorId, int productId, std::s
return ret;
}
-bool HIDDevice::FindHidRawFile(std::string & deviceName, std::string & hidrawFile)
+bool HIDDevice::LookupHidDriverName(std::string &deviceName, std::string &driverName)
{
bool ret = false;
- char hidrawDir[PATH_MAX];
- struct dirent * devDirEntry;
- DIR * devDir;
+ ssize_t sz;
+ char link[PATH_MAX];
+ std::string driverLink = "/sys/bus/hid/devices/" + deviceName + "/driver";
+
+ sz = readlink(driverLink.c_str(), link, PATH_MAX);
+ if (sz == -1)
+ return ret;
- snprintf(hidrawDir, PATH_MAX, "/sys/bus/hid/devices/%s/hidraw", deviceName.c_str());
+ link[sz] = 0;
- devDir = opendir(hidrawDir);
+ driverName = std::string(StripPath(link, PATH_MAX));
+
+ return true;
+}
+
+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);
+ FD_SET(notifyFd, &fds);
+
+ timeout.tv_sec = 20;
+ timeout.tv_usec = 0;
+
+ rc = select(notifyFd + 1, &fds, NULL, NULL, &timeout);
+ if (rc < 0) {
+ if (errno == -EINTR)
+ continue;
+
+ return false;
+ }
+
+ if (rc == 0) {
+ return false;
+ }
+
+ if (FD_ISSET(notifyFd, &fds)) {
+ struct inotify_event * event;
+
+ rc = ioctl(notifyFd, FIONREAD, &eventBytesAvailable);
+ if (rc < 0) {
+ continue;
+ }
+
+ 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;
+
+ hidDeviceName = std::string(link).substr(9, 19);
+
+ 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;
+ }
+ }
+ }
+}
+
+bool HIDDevice::FindDevice(enum RMIDeviceType type)
+{
+ DIR * devDir;
+ struct dirent * devDirEntry;
+ char deviceFile[PATH_MAX];
+ bool found = false;
+ int rc;
+ devDir = opendir("/dev");
if (!devDir)
- return false;
+ return -1;
while ((devDirEntry = readdir(devDir)) != NULL) {
- if (!strncmp(devDirEntry->d_name, "hidraw", 6)) {
- hidrawFile = std::string("/dev/") + devDirEntry->d_name;
- ret = true;
- break;
+ if (strstr(devDirEntry->d_name, "hidraw")) {
+ snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name);
+ fprintf(stdout, "Got device : /dev/%s\n", devDirEntry->d_name);
+ rc = Open(deviceFile);
+ if (rc != 0) {
+ continue;
+ } else if (type != RMI_DEVICE_TYPE_ANY && GetDeviceType() != type) {
+ Close();
+ continue;
+ } else {
+ found = true;
+ break;
+ }
}
}
closedir(devDir);
-
- return ret;
+
+ return found;
}
diff --git a/rmidevice/hiddevice.h b/rmidevice/hiddevice.h
index 05a11fa..b947f62 100644..100755
--- a/rmidevice/hiddevice.h
+++ b/rmidevice/hiddevice.h
@@ -20,8 +20,15 @@
#include <linux/hidraw.h>
#include <string>
+#include <stdint.h>
#include "rmidevice.h"
+enum rmi_hid_mode_type {
+ HID_RMI4_MODE_MOUSE = 0,
+ HID_RMI4_MODE_ATTN_REPORTS = 1,
+ HID_RMI4_MODE_NO_PACKED_ATTN_REPORTS = 2,
+};
+
class HIDDevice : public RMIDevice
{
public:
@@ -30,7 +37,11 @@ public:
m_inputReportSize(0),
m_outputReportSize(0),
m_featureReportSize(0),
- m_deviceOpen(false)
+ m_deviceOpen(false),
+ m_mode(HID_RMI4_MODE_ATTN_REPORTS),
+ 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,
@@ -48,6 +59,9 @@ public:
virtual void PrintDeviceInfo();
+ virtual bool FindDevice(enum RMIDeviceType type = RMI_DEVICE_TYPE_ANY);
+ virtual bool CheckABSEvent();
+
private:
int m_fd;
@@ -67,21 +81,23 @@ private:
bool m_deviceOpen;
- enum mode_type {
- HID_RMI4_MODE_MOUSE = 0,
- HID_RMI4_MODE_ATTN_REPORTS = 1,
- HID_RMI4_MODE_NO_PACKED_ATTN_REPORTS = 2,
- };
+ 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 ParseReportSizes();
+ void ParseReportDescriptor();
+
+ bool WaitForHidRawDevice(int notifyFd, std::string & hidraw);
// static HID utility functions
- static bool LookupHidDeviceName(int bus, int vendorId, int productId, std::string &deviceName);
- static bool FindTransportDevice(int bus, std::string & hidDeviceName,
+ 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 FindHidRawFile(std::string & hidDeviceName, std::string & hidrawFile);
};
#endif /* _HIDDEVICE_H_ */
diff --git a/rmidevice/rmidevice.cpp b/rmidevice/rmidevice.cpp
index 71bafa0..15335f9 100644
--- a/rmidevice/rmidevice.cpp
+++ b/rmidevice/rmidevice.cpp
@@ -50,6 +50,7 @@
#define RMI_DEVICE_F01_QRY43_01_BUILD_ID (1 << 1)
#define PACKAGE_ID_BYTES 4
+#define CONFIG_ID_BYTES 4
#define BUILD_ID_BYTES 3
#define RMI_F01_CMD_DEVICE_RESET 1
@@ -75,10 +76,13 @@ int RMIDevice::QueryBasicProperties()
{
int rc;
unsigned char basicQuery[RMI_DEVICE_F01_BASIC_QUERY_LEN];
+ unsigned char configid[CONFIG_ID_BYTES];
unsigned short queryAddr;
+ unsigned short controlAddr;
unsigned char infoBuf[4];
unsigned short prodInfoAddr;
RMIFunction f01;
+ RMIFunction f34;
SetRMIPage(0x00);
@@ -187,9 +191,30 @@ int RMIDevice::QueryBasicProperties()
}
}
}
+
+ if (GetFunction(f34, 0x34)) {
+ controlAddr = f34.GetControlBase();
+ rc = Read(controlAddr, configid, CONFIG_ID_BYTES);
+ if (rc < 0 || rc < CONFIG_ID_BYTES) {
+ fprintf(stderr, "Failed to read the config id: %s\n", strerror(errno));
+ return rc;
+ }
+ m_configID = (configid[0] << 24 | configid[1] << 16
+ | configid[2] << 8 | configid[3]) & 0xFFFFFFFF;
+ }
+
return 0;
}
+void RMIDevice::Close()
+{
+ m_functionList.clear();
+ m_bCancel = false;
+ m_bytesPerReadRequest = 0;
+ m_page = -1;
+ m_deviceType = RMI_DEVICE_TYPE_ANY;
+}
+
void RMIDevice::PrintProperties()
{
fprintf(stdout, "manufacturerID:\t\t%d\n", m_manufacturerID);
@@ -320,43 +345,4 @@ bool RMIDevice::InBootloader()
return !!(status & 0x40);
}
return true;
-}
-
-long long diff_time(struct timespec *start, struct timespec *end)
-{
- long long diff;
- diff = (end->tv_sec - start->tv_sec) * 1000 * 1000;
- diff += (end->tv_nsec - start->tv_nsec) / 1000;
- return diff;
-}
-
-int Sleep(int ms)
-{
- struct timespec ts;
- struct timespec rem;
-
- ts.tv_sec = ms / 1000;
- ts.tv_nsec = (ms % 1000) * 1000 * 1000;
- for (;;) {
- if (nanosleep(&ts, &rem) == 0) {
- break;
- } else {
- if (errno == EINTR) {
- ts = rem;
- continue;
- }
- return -1;
- }
- }
- return 0;
-}
-
-void print_buffer(const unsigned char *buf, unsigned int len)
-{
- for (unsigned int i = 0; i < len; ++i) {
- fprintf(stdout, "0x%02X ", buf[i]);
- if (i % 8 == 7)
- fprintf(stdout, "\n");
- }
- fprintf(stdout, "\n");
-}
+} \ No newline at end of file
diff --git a/rmidevice/rmidevice.h b/rmidevice/rmidevice.h
index 48de72b..9bfe849 100644
--- a/rmidevice/rmidevice.h
+++ b/rmidevice/rmidevice.h
@@ -27,10 +27,17 @@
#define RMI_INTERUPT_SOURCES_ALL_MASK 0xFFFFFFFF
+enum RMIDeviceType {
+ RMI_DEVICE_TYPE_ANY = 0,
+ RMI_DEVICE_TYPE_TOUCHPAD,
+ RMI_DEVICE_TYPE_TOUCHSCREEN,
+};
+
class RMIDevice
{
public:
- RMIDevice() : m_functionList(), m_sensorID(0), m_bCancel(false), m_bytesPerReadRequest(0), m_page(-1)
+ RMIDevice() : m_functionList(), m_sensorID(0), m_bCancel(false), m_bytesPerReadRequest(0), m_page(-1),
+ m_deviceType(RMI_DEVICE_TYPE_ANY)
{}
virtual ~RMIDevice() {}
virtual int Open(const char * filename) = 0;
@@ -44,11 +51,13 @@ public:
virtual int GetAttentionReport(struct timeval * timeout, unsigned int source_mask,
unsigned char *buf, unsigned int *len)
{ return -1; /* Unsupported */ }
- virtual void Close() = 0;
+ virtual void Close();
virtual void Cancel() { m_bCancel = true; }
virtual void RebindDriver() = 0;
+ virtual bool CheckABSEvent() = 0;
unsigned long GetFirmwareID() { return m_buildID; }
+ unsigned long GetConfigID() { return m_configID; }
int GetFirmwareVersionMajor() { return m_firmwareVersionMajor; }
int GetFirmwareVersionMinor() { return m_firmwareVersionMinor; }
virtual int QueryBasicProperties();
@@ -69,6 +78,9 @@ public:
unsigned int GetNumInterruptRegs() { return m_numInterruptRegs; }
+ virtual bool FindDevice(enum RMIDeviceType type = RMI_DEVICE_TYPE_ANY) = 0;
+ enum RMIDeviceType GetDeviceType() { return m_deviceType; }
+
protected:
std::vector<RMIFunction> m_functionList;
unsigned char m_manufacturerID;
@@ -82,6 +94,7 @@ protected:
unsigned short m_packageID;
unsigned short m_packageRev;
unsigned long m_buildID;
+ unsigned long m_configID;
unsigned char m_sensorID;
unsigned long m_boardID;
@@ -101,10 +114,15 @@ protected:
int m_page;
unsigned int m_numInterruptRegs;
- };
+
+ enum RMIDeviceType m_deviceType;
+};
/* Utility Functions */
long long diff_time(struct timespec *start, struct timespec *end);
int Sleep(int ms);
void print_buffer(const unsigned char *buf, unsigned int len);
+unsigned long extract_long(const unsigned char *data);
+unsigned short extract_short(const unsigned char *data);
+const char * StripPath(const char * path, ssize_t size);
#endif /* _RMIDEVICE_H_ */
diff --git a/rmidevice/util.cpp b/rmidevice/util.cpp
new file mode 100644
index 0000000..64b1c1c
--- /dev/null
+++ b/rmidevice/util.cpp
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <time.h>
+
+long long diff_time(struct timespec *start, struct timespec *end)
+{
+ long long diff;
+ diff = (end->tv_sec - start->tv_sec) * 1000 * 1000;
+ diff += (end->tv_nsec - start->tv_nsec) / 1000;
+ return diff;
+}
+
+int Sleep(int ms)
+{
+ struct timespec ts;
+ struct timespec rem;
+
+ ts.tv_sec = ms / 1000;
+ ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+ for (;;) {
+ if (nanosleep(&ts, &rem) == 0) {
+ break;
+ } else {
+ if (errno == EINTR) {
+ ts = rem;
+ continue;
+ }
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void print_buffer(const unsigned char *buf, unsigned int len)
+{
+ for (unsigned int i = 0; i < len; ++i) {
+ fprintf(stdout, "0x%02X ", buf[i]);
+ if (i % 8 == 7)
+ fprintf(stdout, "\n");
+ }
+ fprintf(stdout, "\n");
+}
+
+
+const char * StripPath(const char * path, ssize_t size)
+{
+ int i;
+ const char * str;
+
+ for (i = size - 1, str = &path[size - 1]; i > 0; --i, --str)
+ if (path[i - 1] == '/')
+ break;
+
+ return str;
+}
+
+unsigned long extract_long(const unsigned char *data)
+{
+ return (unsigned long)data [0]
+ + (unsigned long)data [1] * 0x100
+ + (unsigned long)data [2] * 0x10000
+ + (unsigned long)data [3] * 0x1000000;
+}
+
+unsigned short extract_short(const unsigned char *data)
+{
+ return (unsigned long)data [0]
+ + (unsigned long)data [1] * 0x100;
+} \ No newline at end of file