]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/input/touchscreen/usbtouchscreen.c
Merge branches 'release', 'bugzilla-6217', 'bugzilla-6629', 'bugzilla-6933', 'bugzill...
[linux-2.6-omap-h63xx.git] / drivers / input / touchscreen / usbtouchscreen.c
index 5f34b78d5ddbef126193d13b1c2afc4e8a3600b8..63f9664a066f8465398f4526ca07ee4fbbbf4684 100644 (file)
  *  - DMC TSC-10/25
  *  - IRTOUCHSYSTEMS/UNITOP
  *  - IdealTEK URTC1000
+ *  - General Touch
+ *  - GoTop Super_Q2/GogoPen/PenPower tablets
  *
- * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
+ * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
  *
  * This program is free software; you can redistribute it and/or
@@ -49,7 +51,7 @@
 #include <linux/usb/input.h>
 
 
-#define DRIVER_VERSION         "v0.5"
+#define DRIVER_VERSION         "v0.6"
 #define DRIVER_AUTHOR          "Daniel Ritz <daniel.ritz@gmx.ch>"
 #define DRIVER_DESC            "USB Touchscreen Driver"
 
@@ -64,17 +66,21 @@ struct usbtouch_device_info {
        int min_yc, max_yc;
        int min_press, max_press;
        int rept_size;
-       int flags;
 
        void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
+
+       /*
+        * used to get the packet len. possible return values:
+        * > 0: packet len
+        * = 0: skip one byte
+        * < 0: -return value more bytes needed
+        */
        int  (*get_pkt_len) (unsigned char *pkt, int len);
+
        int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt);
        int  (*init)        (struct usbtouch_usb *usbtouch);
 };
 
-#define USBTOUCH_FLG_BUFFER    0x01
-
-
 /* a usbtouch device */
 struct usbtouch_usb {
        unsigned char *data;
@@ -93,15 +99,6 @@ struct usbtouch_usb {
 };
 
 
-#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK)
-#define MULTI_PACKET
-#endif
-
-#ifdef MULTI_PACKET
-static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
-                                   unsigned char *pkt, int len);
-#endif
-
 /* device types */
 enum {
        DEVTPYE_DUMMY = -1,
@@ -115,6 +112,7 @@ enum {
        DEVTYPE_IRTOUCH,
        DEVTYPE_IDEALTEK,
        DEVTYPE_GENERAL_TOUCH,
+       DEVTYPE_GOTOP,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
@@ -168,6 +166,12 @@ static struct usb_device_id usbtouch_devices[] = {
        {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+       {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP},
+       {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP},
+       {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
+#endif
+
        {}
 };
 
@@ -178,6 +182,10 @@ static struct usb_device_id usbtouch_devices[] = {
 
 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
 
+#ifndef MULTI_PACKET
+#define MULTI_PACKET
+#endif
+
 #define EGALAX_PKT_TYPE_MASK           0xFE
 #define EGALAX_PKT_TYPE_REPT           0x80
 #define EGALAX_PKT_TYPE_DIAG           0x0A
@@ -315,6 +323,9 @@ static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
  * eTurboTouch part
  */
 #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
+#ifndef MULTI_PACKET
+#define MULTI_PACKET
+#endif
 static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
        unsigned int shift;
@@ -453,6 +464,9 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
  * IdealTEK URTC1000 Part
  */
 #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
+#ifndef MULTI_PACKET
+#define MULTI_PACKET
+#endif
 static int idealtek_get_pkt_len(unsigned char *buf, int len)
 {
        if (buf[0] & 0x80)
@@ -500,9 +514,28 @@ static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 }
 #endif
 
+/*****************************************************************************
+ * GoTop Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+       dev->x = ((pkt[1] & 0x38) << 4) | pkt[2];
+       dev->y = ((pkt[1] & 0x07) << 7) | pkt[3];
+       dev->touch = pkt[0] & 0x01;
+       return 1;
+}
+#endif
+
+
 /*****************************************************************************
  * the different device descriptors
  */
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                  unsigned char *pkt, int len);
+#endif
+
 static struct usbtouch_device_info usbtouch_dev_info[] = {
 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
        [DEVTYPE_EGALAX] = {
@@ -511,7 +544,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .min_yc         = 0x0,
                .max_yc         = 0x07ff,
                .rept_size      = 16,
-               .flags          = USBTOUCH_FLG_BUFFER,
                .process_pkt    = usbtouch_process_multi,
                .get_pkt_len    = egalax_get_pkt_len,
                .read_data      = egalax_read_data,
@@ -560,7 +592,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .min_yc         = 0x0,
                .max_yc         = 0x07ff,
                .rept_size      = 8,
-               .flags          = USBTOUCH_FLG_BUFFER,
                .process_pkt    = usbtouch_process_multi,
                .get_pkt_len    = eturbo_get_pkt_len,
                .read_data      = eturbo_read_data,
@@ -608,7 +639,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .min_yc         = 0x0,
                .max_yc         = 0x0fff,
                .rept_size      = 8,
-               .flags          = USBTOUCH_FLG_BUFFER,
                .process_pkt    = usbtouch_process_multi,
                .get_pkt_len    = idealtek_get_pkt_len,
                .read_data      = idealtek_read_data,
@@ -623,9 +653,19 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .max_yc         = 0x0500,
                .rept_size      = 7,
                .read_data      = general_touch_read_data,
-       }
+       },
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+       [DEVTYPE_GOTOP] = {
+               .min_xc         = 0x0,
+               .max_xc         = 0x03ff,
+               .min_yc         = 0x0,
+               .max_yc         = 0x03ff,
+               .rept_size      = 4,
+               .read_data      = gotop_read_data,
+       },
+#endif
 };
 
 
@@ -706,11 +746,14 @@ static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
        pos = 0;
        while (pos < buf_len) {
                /* get packet len */
-               pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len);
+               pkt_len = usbtouch->type->get_pkt_len(buffer + pos,
+                                                       buf_len - pos);
 
-               /* unknown packet: drop everything */
-               if (unlikely(!pkt_len))
-                       goto out_flush_buf;
+               /* unknown packet: skip one byte */
+               if (unlikely(!pkt_len)) {
+                       pos++;
+                       continue;
+               }
 
                /* full packet: process */
                if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
@@ -825,7 +868,7 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!usbtouch->data)
                goto out_free;
 
-       if (type->flags & USBTOUCH_FLG_BUFFER) {
+       if (type->get_pkt_len) {
                usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
                if (!usbtouch->buffer)
                        goto out_free_buffers;