Message ID | 20180703204729.14986-1-nick@shmanahar.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Jul 3, 2018 at 10:47 PM, Nick Dyer <nick@shmanahar.org> 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@shmanahar.org> > --- > 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@aleksander.es> > 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 >
Hi Nick, On Tue, Jul 03, 2018 at 09:47:29PM +0100, Nick Dyer 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. What is the intended use of this data? Can it be fetched by an userspace utility accessing device over usbfs? Thanks.
Where I work we use this data to determine if there are broken traces between the touchscreen and the touchscreen controller. When a trace is broken, the absolute value of one of the 4 corners is a small fraction of the other three. With our flying systems, we have a shell script that reads the sysfs entry and writes it to the syslog on every system boot. With the sysfs entry, we are able to avoid dependency on any userspace utilities for accessing this data. On Wed, Jul 25, 2018 at 4:33 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > Hi Nick, > > On Tue, Jul 03, 2018 at 09:47:29PM +0100, Nick Dyer 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. > > What is the intended use of this data? Can it be fetched by an userspace > utility accessing device over usbfs? > > Thanks. > > -- > Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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);
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> --- Changes in v2: - Values read from device must be treated as signed drivers/input/touchscreen/usbtouchscreen.c | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+)