@@ -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);
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(+)