diff mbox

[v1] Input: usbtouchscreen - add strays output via sysfs

Message ID 20180517184734.13461-1-nick@shmanahar.org (mailing list archive)
State New, archived
Headers show

Commit Message

Nick Dyer May 17, 2018, 6:47 p.m. UTC
With surface capacitance touchscreens the capacitance is measured
through readings obtained from measurements taken at the four
corners of the glass.  These measurements are accessible in the I/Q
modulation format from the the controller which becomes meaningful
data when converted to an absolute value using the pythagorean
theorem.

Signed-off-by: Nick Dyer <nick@shmanahar.org>
---
 drivers/input/touchscreen/usbtouchscreen.c | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)
diff mbox

Patch

diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index d61570d64ee7..742abd158b08 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -55,6 +55,7 @@ 
 #include <linux/usb/input.h>
 #include <linux/hid.h>
 #include <linux/mutex.h>
+#include <asm/unaligned.h>
 
 static bool swap_xy;
 module_param(swap_xy, bool, 0644);
@@ -437,11 +438,18 @@  static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 #ifdef CONFIG_TOUCHSCREEN_USB_3M
 
 #define MTOUCHUSB_ASYNC_REPORT          1
+#define MTOUCHUSB_GET_BLOCK		2
+#define MTOUCHUSB_STRAYS_BLOCK_CMD	3
 #define MTOUCHUSB_RESET                 7
 #define MTOUCHUSB_REQ_CTRLLR_ID         10
 
 #define MTOUCHUSB_REQ_CTRLLR_ID_LEN	16
 
+struct mtouch_strays {
+	u8 hdr[3];
+	__le32 data[8];
+} __attribute__ ((packed));
+
 static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	if (hwcalib_xy) {
@@ -459,8 +467,22 @@  static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 struct mtouch_priv {
 	u8 fw_rev_major;
 	u8 fw_rev_minor;
+	u64 strays[4];
 };
 
+static ssize_t mtouch_strays_show(struct device *dev,
+				  struct device_attribute *attr, char *output)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+	struct mtouch_priv *priv = usbtouch->priv;
+
+	return scnprintf(output, PAGE_SIZE, "ul=%llu ur=%llu ll=%llu lr=%llu\n",
+			 priv->strays[0], priv->strays[1],
+			 priv->strays[2], priv->strays[3]);
+}
+static DEVICE_ATTR(strays, 0444, mtouch_strays_show, NULL);
+
 static ssize_t mtouch_firmware_rev_show(struct device *dev,
 				struct device_attribute *attr, char *output)
 {
@@ -475,6 +497,7 @@  static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL);
 
 static struct attribute *mtouch_attrs[] = {
 	&dev_attr_firmware_rev.attr,
+	&dev_attr_strays.attr,
 	NULL
 };
 
@@ -482,6 +505,39 @@  static const struct attribute_group mtouch_attr_group = {
 	.attrs = mtouch_attrs,
 };
 
+static void mtouch_get_strays_report(struct usbtouch_usb *usbtouch)
+{
+	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
+	struct mtouch_priv *priv = usbtouch->priv;
+	struct mtouch_strays *sbuf;
+	int ret;
+	int i;
+
+	sbuf = kzalloc(sizeof(struct mtouch_strays), GFP_NOIO);
+	if (!sbuf)
+		return;
+
+	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			      MTOUCHUSB_GET_BLOCK,
+			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      MTOUCHUSB_STRAYS_BLOCK_CMD,
+			      0, sbuf, sizeof(struct mtouch_strays),
+			      USB_CTRL_SET_TIMEOUT);
+	if (ret != sizeof(struct mtouch_strays))
+		goto out_free;
+
+	for (i = 0; i < 4; i++) {
+		u64 a, b;
+
+		a = get_unaligned_le32(&sbuf->data[i*2]);
+		b = get_unaligned_le32(&sbuf->data[i*2 + 1]);
+		priv->strays[i] = int_sqrt64(a * a + b * b);
+	}
+
+out_free:
+	kfree(sbuf);
+}
+
 static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch)
 {
 	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
@@ -568,6 +624,8 @@  static int mtouch_init(struct usbtouch_usb *usbtouch)
 			return ret;
 	}
 
+	mtouch_get_strays_report(usbtouch);
+
 	/* Default min/max xy are the raw values, override if using hw-calib */
 	if (hwcalib_xy) {
 		input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0);