On Tue, Jul 3, 2018 at 10:47 PM, Nick Dyer <nick@xxxxxxxxxxxxx> wrote: > 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@xxxxxxxxxxxxx> > --- > Changes in v2: > - Values read from device must be treated as signed > Numbers validated against a user-space tool that also reads stray values from the controller. Tested-by: Aleksander Morgado <aleksander@xxxxxxxxxxxxx> > drivers/input/touchscreen/usbtouchscreen.c | 58 ++++++++++++++++++++++ > 1 file changed, 58 insertions(+) > > diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c > index d61570d64ee7..af8fb1ab3a67 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++) { > + s64 a, b; > + > + a = (s32)get_unaligned_le32(&sbuf->data[i*2]); > + b = (s32)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); > -- > 2.17.1 > -- Aleksander https://aleksander.es -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html