aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Ritz <daniel.ritz-ml@swissonline.ch>2008-01-17 12:01:18 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-01-17 12:01:18 -0500
commit62aa366d9b0158a81eace3b83e6b027789f7575b (patch)
treee4cfc7b8c93189ce02aa1b8c32a81fa02f18351f /drivers
parent6724f93463c332018e05f538a2ab3ce41eac0e8a (diff)
Input: usbtouchscreen - fix buffer overflow, make more egalax work
Fix a buffer overflow in mutli-packet handling code. The overflow can only happen with eGalax devices and is even there very unlikely (only non-report packet are affected any only when truncated after the first byte). Also changes the mutli-packet handling code not to drop unknown packets, but rather just drop one byte. This allows synchronizing on report packets in the data stream. It's required for some egalax devices to work at all. Also remove the pointless 'flags' member of the device struct and set the version number to 0.6, plus some minor cleanups. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 19055e7381f8..63f9664a066f 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -11,6 +11,7 @@
11 * - DMC TSC-10/25 11 * - DMC TSC-10/25
12 * - IRTOUCHSYSTEMS/UNITOP 12 * - IRTOUCHSYSTEMS/UNITOP
13 * - IdealTEK URTC1000 13 * - IdealTEK URTC1000
14 * - General Touch
14 * - GoTop Super_Q2/GogoPen/PenPower tablets 15 * - GoTop Super_Q2/GogoPen/PenPower tablets
15 * 16 *
16 * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 17 * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
@@ -50,7 +51,7 @@
50#include <linux/usb/input.h> 51#include <linux/usb/input.h>
51 52
52 53
53#define DRIVER_VERSION "v0.5" 54#define DRIVER_VERSION "v0.6"
54#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 55#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
55#define DRIVER_DESC "USB Touchscreen Driver" 56#define DRIVER_DESC "USB Touchscreen Driver"
56 57
@@ -65,17 +66,21 @@ struct usbtouch_device_info {
65 int min_yc, max_yc; 66 int min_yc, max_yc;
66 int min_press, max_press; 67 int min_press, max_press;
67 int rept_size; 68 int rept_size;
68 int flags;
69 69
70 void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); 70 void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
71
72 /*
73 * used to get the packet len. possible return values:
74 * > 0: packet len
75 * = 0: skip one byte
76 * < 0: -return value more bytes needed
77 */
71 int (*get_pkt_len) (unsigned char *pkt, int len); 78 int (*get_pkt_len) (unsigned char *pkt, int len);
79
72 int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); 80 int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
73 int (*init) (struct usbtouch_usb *usbtouch); 81 int (*init) (struct usbtouch_usb *usbtouch);
74}; 82};
75 83
76#define USBTOUCH_FLG_BUFFER 0x01
77
78
79/* a usbtouch device */ 84/* a usbtouch device */
80struct usbtouch_usb { 85struct usbtouch_usb {
81 unsigned char *data; 86 unsigned char *data;
@@ -94,15 +99,6 @@ struct usbtouch_usb {
94}; 99};
95 100
96 101
97#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK)
98#define MULTI_PACKET
99#endif
100
101#ifdef MULTI_PACKET
102static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
103 unsigned char *pkt, int len);
104#endif
105
106/* device types */ 102/* device types */
107enum { 103enum {
108 DEVTPYE_DUMMY = -1, 104 DEVTPYE_DUMMY = -1,
@@ -186,6 +182,10 @@ static struct usb_device_id usbtouch_devices[] = {
186 182
187#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 183#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
188 184
185#ifndef MULTI_PACKET
186#define MULTI_PACKET
187#endif
188
189#define EGALAX_PKT_TYPE_MASK 0xFE 189#define EGALAX_PKT_TYPE_MASK 0xFE
190#define EGALAX_PKT_TYPE_REPT 0x80 190#define EGALAX_PKT_TYPE_REPT 0x80
191#define EGALAX_PKT_TYPE_DIAG 0x0A 191#define EGALAX_PKT_TYPE_DIAG 0x0A
@@ -323,6 +323,9 @@ static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
323 * eTurboTouch part 323 * eTurboTouch part
324 */ 324 */
325#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 325#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
326#ifndef MULTI_PACKET
327#define MULTI_PACKET
328#endif
326static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 329static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
327{ 330{
328 unsigned int shift; 331 unsigned int shift;
@@ -461,6 +464,9 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
461 * IdealTEK URTC1000 Part 464 * IdealTEK URTC1000 Part
462 */ 465 */
463#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 466#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
467#ifndef MULTI_PACKET
468#define MULTI_PACKET
469#endif
464static int idealtek_get_pkt_len(unsigned char *buf, int len) 470static int idealtek_get_pkt_len(unsigned char *buf, int len)
465{ 471{
466 if (buf[0] & 0x80) 472 if (buf[0] & 0x80)
@@ -525,6 +531,11 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
525/***************************************************************************** 531/*****************************************************************************
526 * the different device descriptors 532 * the different device descriptors
527 */ 533 */
534#ifdef MULTI_PACKET
535static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
536 unsigned char *pkt, int len);
537#endif
538
528static struct usbtouch_device_info usbtouch_dev_info[] = { 539static struct usbtouch_device_info usbtouch_dev_info[] = {
529#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 540#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
530 [DEVTYPE_EGALAX] = { 541 [DEVTYPE_EGALAX] = {
@@ -533,7 +544,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
533 .min_yc = 0x0, 544 .min_yc = 0x0,
534 .max_yc = 0x07ff, 545 .max_yc = 0x07ff,
535 .rept_size = 16, 546 .rept_size = 16,
536 .flags = USBTOUCH_FLG_BUFFER,
537 .process_pkt = usbtouch_process_multi, 547 .process_pkt = usbtouch_process_multi,
538 .get_pkt_len = egalax_get_pkt_len, 548 .get_pkt_len = egalax_get_pkt_len,
539 .read_data = egalax_read_data, 549 .read_data = egalax_read_data,
@@ -582,7 +592,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
582 .min_yc = 0x0, 592 .min_yc = 0x0,
583 .max_yc = 0x07ff, 593 .max_yc = 0x07ff,
584 .rept_size = 8, 594 .rept_size = 8,
585 .flags = USBTOUCH_FLG_BUFFER,
586 .process_pkt = usbtouch_process_multi, 595 .process_pkt = usbtouch_process_multi,
587 .get_pkt_len = eturbo_get_pkt_len, 596 .get_pkt_len = eturbo_get_pkt_len,
588 .read_data = eturbo_read_data, 597 .read_data = eturbo_read_data,
@@ -630,7 +639,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
630 .min_yc = 0x0, 639 .min_yc = 0x0,
631 .max_yc = 0x0fff, 640 .max_yc = 0x0fff,
632 .rept_size = 8, 641 .rept_size = 8,
633 .flags = USBTOUCH_FLG_BUFFER,
634 .process_pkt = usbtouch_process_multi, 642 .process_pkt = usbtouch_process_multi,
635 .get_pkt_len = idealtek_get_pkt_len, 643 .get_pkt_len = idealtek_get_pkt_len,
636 .read_data = idealtek_read_data, 644 .read_data = idealtek_read_data,
@@ -738,11 +746,14 @@ static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
738 pos = 0; 746 pos = 0;
739 while (pos < buf_len) { 747 while (pos < buf_len) {
740 /* get packet len */ 748 /* get packet len */
741 pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len); 749 pkt_len = usbtouch->type->get_pkt_len(buffer + pos,
750 buf_len - pos);
742 751
743 /* unknown packet: drop everything */ 752 /* unknown packet: skip one byte */
744 if (unlikely(!pkt_len)) 753 if (unlikely(!pkt_len)) {
745 goto out_flush_buf; 754 pos++;
755 continue;
756 }
746 757
747 /* full packet: process */ 758 /* full packet: process */
748 if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 759 if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
@@ -857,7 +868,7 @@ static int usbtouch_probe(struct usb_interface *intf,
857 if (!usbtouch->data) 868 if (!usbtouch->data)
858 goto out_free; 869 goto out_free;
859 870
860 if (type->flags & USBTOUCH_FLG_BUFFER) { 871 if (type->get_pkt_len) {
861 usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 872 usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
862 if (!usbtouch->buffer) 873 if (!usbtouch->buffer)
863 goto out_free_buffers; 874 goto out_free_buffers;