aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Duggan <aduggan@synaptics.com>2014-06-18 13:11:49 -0700
committerAndrew Duggan <aduggan@synaptics.com>2014-06-18 13:11:49 -0700
commit8b77439d5c8900ab307da3d207665920b52d949e (patch)
tree69d8080654fc8dc53864ac52c5bf57447569ac87
parenta90829bd42fc7c0dc5e901376397ef22aa9b09a4 (diff)
downloadrmi4utils-8b77439d5c8900ab307da3d207665920b52d949e.tar.gz
Parse the size of the HID reports from the HID Report Descriptor.
-rw-r--r--rmidevice/hiddevice.cpp90
-rw-r--r--rmidevice/hiddevice.h1
2 files changed, 87 insertions, 4 deletions
diff --git a/rmidevice/hiddevice.cpp b/rmidevice/hiddevice.cpp
index 8b99d75..1345db2 100644
--- a/rmidevice/hiddevice.cpp
+++ b/rmidevice/hiddevice.cpp
@@ -45,6 +45,13 @@ enum rmi_hid_mode_type {
HID_RMI4_MODE_NO_PACKED_ATTN_REPORTS = 2,
};
+enum hid_report_type {
+ HID_REPORT_TYPE_UNKNOWN = 0x0,
+ HID_REPORT_TYPE_INPUT = 0x81,
+ HID_REPORT_TYPE_OUTPUT = 0x91,
+ HID_REPORT_TYPE_FEATURE = 0xb1,
+};
+
#define HID_RMI4_REPORT_ID 0
#define HID_RMI4_READ_INPUT_COUNT 1
#define HID_RMI4_READ_INPUT_DATA 2
@@ -85,10 +92,7 @@ int HIDDevice::Open(const char * filename)
if (rc < 0)
return rc;
- /* FIXME: get there from the report descriptor */
- m_inputReportSize = 30;
- m_outputReportSize = 25;
- m_featureReportSize = 2;
+ ParseReportSizes();
m_inputReport = new unsigned char[m_inputReportSize]();
if (!m_inputReport)
@@ -115,6 +119,84 @@ int HIDDevice::Open(const char * filename)
return 0;
}
+void HIDDevice::ParseReportSizes()
+{
+ bool isVendorSpecific = false;
+ bool isReport = false;
+ int totalReportSize = 0;
+ int reportSize = 0;
+ int reportCount = 0;
+ enum hid_report_type hidReportType = HID_REPORT_TYPE_UNKNOWN;
+
+ for (unsigned int i = 0; i < m_rptDesc.size; ++i) {
+ if (isVendorSpecific) {
+ if (m_rptDesc.value[i] == 0x85 || m_rptDesc.value[i] == 0xc0) {
+ if (isReport) {
+ // finish up data on the previous report
+ totalReportSize = (reportSize * reportCount) >> 3;
+
+ switch (hidReportType) {
+ case HID_REPORT_TYPE_INPUT:
+ m_inputReportSize = totalReportSize + 1;
+ break;
+ case HID_REPORT_TYPE_OUTPUT:
+ m_outputReportSize = totalReportSize + 1;
+ break;
+ case HID_REPORT_TYPE_FEATURE:
+ m_featureReportSize = totalReportSize + 1;
+ break;
+ case HID_REPORT_TYPE_UNKNOWN:
+ default:
+ break;
+ }
+ }
+
+ // reset values for the new report
+ totalReportSize = 0;
+ reportSize = 0;
+ 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;
+ }
+
+ if (isReport) {
+ if (m_rptDesc.value[i] == 0x75) {
+ reportSize = m_rptDesc.value[++i];
+ continue;
+ }
+
+ if (m_rptDesc.value[i] == 0x95) {
+ reportCount = m_rptDesc.value[++i];
+ continue;
+ }
+
+ if (m_rptDesc.value[i] == HID_REPORT_TYPE_INPUT)
+ hidReportType = HID_REPORT_TYPE_INPUT;
+
+ if (m_rptDesc.value[i] == HID_REPORT_TYPE_OUTPUT)
+ hidReportType = HID_REPORT_TYPE_OUTPUT;
+
+ if (m_rptDesc.value[i] == HID_REPORT_TYPE_FEATURE) {
+ hidReportType = HID_REPORT_TYPE_FEATURE;
+ }
+ }
+ }
+
+ if (m_rptDesc.value[i] == 0x06 && m_rptDesc.value[i + 1] == 0x00
+ && m_rptDesc.value[i + 2] == 0xFF) {
+ isVendorSpecific = true;
+ i += 2;
+ }
+ }
+}
+
int HIDDevice::Read(unsigned short addr, unsigned char *buf, unsigned short len)
{
size_t count;
diff --git a/rmidevice/hiddevice.h b/rmidevice/hiddevice.h
index fb3c848..f086f42 100644
--- a/rmidevice/hiddevice.h
+++ b/rmidevice/hiddevice.h
@@ -70,6 +70,7 @@ private:
int GetReport(int reportid, struct timeval * timeout = NULL);
void PrintReport(const unsigned char *report);
+ void ParseReportSizes();
static const int HID_REPORT_QUEUE_MAX_SIZE = 8;
};