*  - DMC TSC-10/25
  *  - IRTOUCHSYSTEMS/UNITOP
  *  - IdealTEK URTC1000
+ *  - General Touch
  *  - GoTop Super_Q2/GogoPen/PenPower tablets
  *
  * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
 #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"
 
        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;
 };
 
 
-#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,
 
 #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
  * 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;
  * 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)
 /*****************************************************************************
  * 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] = {
                .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,
                .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,
                .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,
        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))) {
        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;