diff mbox series

[v2,09/23] HID: uclogic: Support fragmented high-res reports

Message ID 20190210101409.3511-10-spbnick@gmail.com (mailing list archive)
State Mainlined
Commit 59f2e0fca8ca84f02a718c0f3cd72990d03545be
Delegated to: Jiri Kosina
Headers show
Series [v2,01/23] HID: kye: Add support for EasyPen M406XE | expand

Commit Message

Nikolai Kondrashov Feb. 10, 2019, 10:13 a.m. UTC
Support parsing fragmented high-resolution reports in hid-uclogic to
support v2 reporting protocol.

Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
---
 drivers/hid/hid-uclogic-core.c   | 25 +++++++++++++++++++++++++
 drivers/hid/hid-uclogic-params.h |  8 ++++++++
 2 files changed, 33 insertions(+)
diff mbox series

Patch

diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
index 206642802ca5..81693183d647 100644
--- a/drivers/hid/hid-uclogic-core.c
+++ b/drivers/hid/hid-uclogic-core.c
@@ -265,6 +265,31 @@  static int uclogic_raw_event(struct hid_device *hdev,
 			/* Invert the in-range bit */
 			data[1] ^= 0x40;
 		}
+		/*
+		 * If report contains fragmented high-resolution pen
+		 * coordinates
+		 */
+		if (size >= 10 && params->pen.fragmented_hires) {
+			u8 pressure_low_byte;
+			u8 pressure_high_byte;
+
+			/* Lift pressure bytes */
+			pressure_low_byte = data[6];
+			pressure_high_byte = data[7];
+			/*
+			 * Move Y coord to make space for high-order X
+			 * coord byte
+			 */
+			data[6] = data[5];
+			data[5] = data[4];
+			/* Move high-order X coord byte */
+			data[4] = data[8];
+			/* Move high-order Y coord byte */
+			data[7] = data[9];
+			/* Place pressure bytes */
+			data[8] = pressure_low_byte;
+			data[9] = pressure_high_byte;
+		}
 		/* If we need to emulate in-range detection */
 		if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) {
 			/* Set in-range bit */
diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h
index 665954d6ba57..1060f70d647d 100644
--- a/drivers/hid/hid-uclogic-params.h
+++ b/drivers/hid/hid-uclogic-params.h
@@ -56,6 +56,12 @@  struct uclogic_params_pen {
 	unsigned int id;
 	/* Type of in-range reporting, only valid if "id" is not zero */
 	enum uclogic_params_pen_inrange inrange;
+	/*
+	 * True, if reports include fragmented high resolution coords, with
+	 * high-order X and then Y bytes following the pressure field.
+	 * Only valid if "id" is not zero.
+	 */
+	bool fragmented_hires;
 };
 
 /*
@@ -151,6 +157,7 @@  extern int uclogic_params_init(struct uclogic_params *params,
 		".pen.desc_size = %u\n"             \
 		".pen.id = %u\n"                    \
 		".pen.inrange = %s\n"               \
+		".pen.fragmented_hires = %s\n"      \
 		".frame.desc_ptr = %p\n"            \
 		".frame.desc_size = %u\n"           \
 		".frame.id = %u\n"                  \
@@ -166,6 +173,7 @@  extern int uclogic_params_init(struct uclogic_params *params,
 		(_params)->pen.desc_size,                                   \
 		(_params)->pen.id,                                          \
 		uclogic_params_pen_inrange_to_str((_params)->pen.inrange),  \
+		((_params)->pen.fragmented_hires ? "true" : "false"),       \
 		(_params)->frame.desc_ptr,                                  \
 		(_params)->frame.desc_size,                                 \
 		(_params)->frame.id,                                        \