| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1 | /****************************************************************************** | 
|  | 2 | * usbtouchscreen.c | 
|  | 3 | * Driver for USB Touchscreens, supporting those devices: | 
|  | 4 | *  - eGalax Touchkit | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 5 | *    includes eTurboTouch CT-410/510/700 | 
|  | 6 | *  - 3M/Microtouch  EX II series | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 7 | *  - ITM | 
|  | 8 | *  - PanJit TouchSet | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 9 | *  - eTurboTouch | 
|  | 10 | *  - Gunze AHL61 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 11 | *  - DMC TSC-10/25 | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 12 | *  - IRTOUCHSYSTEMS/UNITOP | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 13 | *  - IdealTEK URTC1000 | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 14 | *  - General Touch | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 15 | *  - GoTop Super_Q2/GogoPen/PenPower tablets | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 16 | * | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 17 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 18 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 
|  | 19 | * | 
|  | 20 | * This program is free software; you can redistribute it and/or | 
|  | 21 | * modify it under the terms of the GNU General Public License as | 
|  | 22 | * published by the Free Software Foundation; either version 2 of the | 
|  | 23 | * License, or (at your option) any later version. | 
|  | 24 | * | 
|  | 25 | * This program is distributed in the hope that it will be useful, but | 
|  | 26 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 28 | * General Public License for more details. | 
|  | 29 | * | 
|  | 30 | * You should have received a copy of the GNU General Public License | 
|  | 31 | * along with this program; if not, write to the Free Software | 
|  | 32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 33 | * | 
|  | 34 | * Driver is based on touchkitusb.c | 
|  | 35 | * - ITM parts are from itmtouch.c | 
|  | 36 | * - 3M parts are from mtouchusb.c | 
|  | 37 | * - PanJit parts are from an unmerged driver by Lanslott Gish | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 38 | * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged | 
|  | 39 | *   driver from Marius Vollmer | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 40 | * | 
|  | 41 | *****************************************************************************/ | 
|  | 42 |  | 
|  | 43 | //#define DEBUG | 
|  | 44 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 45 | #include <linux/kernel.h> | 
|  | 46 | #include <linux/slab.h> | 
|  | 47 | #include <linux/input.h> | 
|  | 48 | #include <linux/module.h> | 
|  | 49 | #include <linux/init.h> | 
|  | 50 | #include <linux/usb.h> | 
| David Brownell | ae0dadc | 2006-06-13 10:04:34 -0700 | [diff] [blame] | 51 | #include <linux/usb/input.h> | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 52 |  | 
|  | 53 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 54 | #define DRIVER_VERSION		"v0.6" | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 55 | #define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>" | 
|  | 56 | #define DRIVER_DESC		"USB Touchscreen Driver" | 
|  | 57 |  | 
|  | 58 | static int swap_xy; | 
|  | 59 | module_param(swap_xy, bool, 0644); | 
|  | 60 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 
|  | 61 |  | 
|  | 62 | /* device specifc data/functions */ | 
|  | 63 | struct usbtouch_usb; | 
|  | 64 | struct usbtouch_device_info { | 
|  | 65 | int min_xc, max_xc; | 
|  | 66 | int min_yc, max_yc; | 
|  | 67 | int min_press, max_press; | 
|  | 68 | int rept_size; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 69 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 70 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 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 | */ | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 78 | int  (*get_pkt_len) (unsigned char *pkt, int len); | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 79 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 80 | int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 81 | int  (*init)        (struct usbtouch_usb *usbtouch); | 
|  | 82 | }; | 
|  | 83 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 84 | /* a usbtouch device */ | 
|  | 85 | struct usbtouch_usb { | 
|  | 86 | unsigned char *data; | 
|  | 87 | dma_addr_t data_dma; | 
|  | 88 | unsigned char *buffer; | 
|  | 89 | int buf_len; | 
|  | 90 | struct urb *irq; | 
|  | 91 | struct usb_device *udev; | 
|  | 92 | struct input_dev *input; | 
|  | 93 | struct usbtouch_device_info *type; | 
|  | 94 | char name[128]; | 
|  | 95 | char phys[64]; | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 96 |  | 
|  | 97 | int x, y; | 
|  | 98 | int touch, press; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 99 | }; | 
|  | 100 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 101 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 102 | /* device types */ | 
|  | 103 | enum { | 
|  | 104 | DEVTPYE_DUMMY = -1, | 
|  | 105 | DEVTYPE_EGALAX, | 
|  | 106 | DEVTYPE_PANJIT, | 
|  | 107 | DEVTYPE_3M, | 
|  | 108 | DEVTYPE_ITM, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 109 | DEVTYPE_ETURBO, | 
|  | 110 | DEVTYPE_GUNZE, | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 111 | DEVTYPE_DMC_TSC10, | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 112 | DEVTYPE_IRTOUCH, | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 113 | DEVTYPE_IDEALTEK, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 114 | DEVTYPE_GENERAL_TOUCH, | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 115 | DEVTYPE_GOTOP, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 116 | }; | 
|  | 117 |  | 
|  | 118 | static struct usb_device_id usbtouch_devices[] = { | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 119 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 120 | {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 121 | {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 122 | {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 123 | {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 124 | {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 125 | {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 126 | {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 127 | #endif | 
|  | 128 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 129 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 130 | {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, | 
|  | 131 | {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, | 
|  | 132 | {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, | 
|  | 133 | {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, | 
|  | 134 | #endif | 
|  | 135 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 136 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 137 | {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, | 
|  | 138 | #endif | 
|  | 139 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 140 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 141 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, | 
|  | 142 | #endif | 
|  | 143 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 144 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 145 | {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, | 
|  | 146 | #endif | 
|  | 147 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 148 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 149 | {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, | 
|  | 150 | #endif | 
|  | 151 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 152 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 153 | {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, | 
|  | 154 | #endif | 
|  | 155 |  | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 156 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 157 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 
|  | 158 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 
|  | 159 | #endif | 
|  | 160 |  | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 161 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
|  | 162 | {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, | 
|  | 163 | #endif | 
|  | 164 |  | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 165 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 166 | {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, | 
|  | 167 | #endif | 
|  | 168 |  | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 169 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 170 | {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, | 
|  | 171 | {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, | 
|  | 172 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 
|  | 173 | #endif | 
|  | 174 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 175 | {} | 
|  | 176 | }; | 
|  | 177 |  | 
|  | 178 |  | 
|  | 179 | /***************************************************************************** | 
|  | 180 | * eGalax part | 
|  | 181 | */ | 
|  | 182 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 183 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 184 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 185 | #ifndef MULTI_PACKET | 
|  | 186 | #define MULTI_PACKET | 
|  | 187 | #endif | 
|  | 188 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 189 | #define EGALAX_PKT_TYPE_MASK		0xFE | 
|  | 190 | #define EGALAX_PKT_TYPE_REPT		0x80 | 
|  | 191 | #define EGALAX_PKT_TYPE_DIAG		0x0A | 
|  | 192 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 193 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 194 | { | 
|  | 195 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) | 
|  | 196 | return 0; | 
|  | 197 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 198 | dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); | 
|  | 199 | dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); | 
|  | 200 | dev->touch = pkt[0] & 0x01; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 201 |  | 
|  | 202 | return 1; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 203 | } | 
|  | 204 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 205 | static int egalax_get_pkt_len(unsigned char *buf, int len) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 206 | { | 
|  | 207 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { | 
|  | 208 | case EGALAX_PKT_TYPE_REPT: | 
|  | 209 | return 5; | 
|  | 210 |  | 
|  | 211 | case EGALAX_PKT_TYPE_DIAG: | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 212 | if (len < 2) | 
|  | 213 | return -1; | 
|  | 214 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 215 | return buf[1] + 2; | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 | return 0; | 
|  | 219 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 220 | #endif | 
|  | 221 |  | 
|  | 222 |  | 
|  | 223 | /***************************************************************************** | 
|  | 224 | * PanJit Part | 
|  | 225 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 226 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 227 | static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 228 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 229 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | 
|  | 230 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | 
|  | 231 | dev->touch = pkt[0] & 0x01; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 232 |  | 
|  | 233 | return 1; | 
|  | 234 | } | 
|  | 235 | #endif | 
|  | 236 |  | 
|  | 237 |  | 
|  | 238 | /***************************************************************************** | 
|  | 239 | * 3M/Microtouch Part | 
|  | 240 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 241 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 242 |  | 
|  | 243 | #define MTOUCHUSB_ASYNC_REPORT          1 | 
|  | 244 | #define MTOUCHUSB_RESET                 7 | 
|  | 245 | #define MTOUCHUSB_REQ_CTRLLR_ID         10 | 
|  | 246 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 247 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 248 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 249 | dev->x = (pkt[8] << 8) | pkt[7]; | 
|  | 250 | dev->y = (pkt[10] << 8) | pkt[9]; | 
|  | 251 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 252 |  | 
|  | 253 | return 1; | 
|  | 254 | } | 
|  | 255 |  | 
|  | 256 | static int mtouch_init(struct usbtouch_usb *usbtouch) | 
|  | 257 | { | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 258 | int ret, i; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 259 |  | 
|  | 260 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 
|  | 261 | MTOUCHUSB_RESET, | 
|  | 262 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 263 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 264 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | 
|  | 265 | __FUNCTION__, ret); | 
|  | 266 | if (ret < 0) | 
|  | 267 | return ret; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 268 | msleep(150); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 269 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 270 | for (i = 0; i < 3; i++) { | 
|  | 271 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 
|  | 272 | MTOUCHUSB_ASYNC_REPORT, | 
|  | 273 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 274 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 275 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | 
|  | 276 | __FUNCTION__, ret); | 
|  | 277 | if (ret >= 0) | 
|  | 278 | break; | 
|  | 279 | if (ret != -EPIPE) | 
|  | 280 | return ret; | 
|  | 281 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 282 |  | 
|  | 283 | return 0; | 
|  | 284 | } | 
|  | 285 | #endif | 
|  | 286 |  | 
|  | 287 |  | 
|  | 288 | /***************************************************************************** | 
|  | 289 | * ITM Part | 
|  | 290 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 291 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 292 | static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 293 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 294 | int touch; | 
|  | 295 | /* | 
|  | 296 | * ITM devices report invalid x/y data if not touched. | 
|  | 297 | * if the screen was touched before but is not touched any more | 
|  | 298 | * report touch as 0 with the last valid x/y data once. then stop | 
|  | 299 | * reporting data until touched again. | 
|  | 300 | */ | 
|  | 301 | dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 302 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 303 | touch = ~pkt[7] & 0x20; | 
|  | 304 | if (!touch) { | 
|  | 305 | if (dev->touch) { | 
|  | 306 | dev->touch = 0; | 
|  | 307 | return 1; | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | return 0; | 
|  | 311 | } | 
|  | 312 |  | 
|  | 313 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); | 
|  | 314 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); | 
|  | 315 | dev->touch = touch; | 
|  | 316 |  | 
|  | 317 | return 1; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 318 | } | 
|  | 319 | #endif | 
|  | 320 |  | 
|  | 321 |  | 
|  | 322 | /***************************************************************************** | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 323 | * eTurboTouch part | 
|  | 324 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 325 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 326 | #ifndef MULTI_PACKET | 
|  | 327 | #define MULTI_PACKET | 
|  | 328 | #endif | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 329 | static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 330 | { | 
|  | 331 | unsigned int shift; | 
|  | 332 |  | 
|  | 333 | /* packets should start with sync */ | 
|  | 334 | if (!(pkt[0] & 0x80)) | 
|  | 335 | return 0; | 
|  | 336 |  | 
|  | 337 | shift = (6 - (pkt[0] & 0x03)); | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 338 | dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; | 
|  | 339 | dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; | 
|  | 340 | dev->touch = (pkt[0] & 0x10) ? 1 : 0; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 341 |  | 
|  | 342 | return 1; | 
|  | 343 | } | 
|  | 344 |  | 
|  | 345 | static int eturbo_get_pkt_len(unsigned char *buf, int len) | 
|  | 346 | { | 
|  | 347 | if (buf[0] & 0x80) | 
|  | 348 | return 5; | 
|  | 349 | if (buf[0] == 0x01) | 
|  | 350 | return 3; | 
|  | 351 | return 0; | 
|  | 352 | } | 
|  | 353 | #endif | 
|  | 354 |  | 
|  | 355 |  | 
|  | 356 | /***************************************************************************** | 
|  | 357 | * Gunze part | 
|  | 358 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 359 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 360 | static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 361 | { | 
|  | 362 | if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) | 
|  | 363 | return 0; | 
|  | 364 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 365 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); | 
|  | 366 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); | 
|  | 367 | dev->touch = pkt[0] & 0x20; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 368 |  | 
|  | 369 | return 1; | 
|  | 370 | } | 
|  | 371 | #endif | 
|  | 372 |  | 
|  | 373 | /***************************************************************************** | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 374 | * DMC TSC-10/25 Part | 
|  | 375 | * | 
|  | 376 | * Documentation about the controller and it's protocol can be found at | 
|  | 377 | *   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf | 
|  | 378 | *   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf | 
|  | 379 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 380 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 381 |  | 
|  | 382 | /* supported data rates. currently using 130 */ | 
|  | 383 | #define TSC10_RATE_POINT	0x50 | 
|  | 384 | #define TSC10_RATE_30		0x40 | 
|  | 385 | #define TSC10_RATE_50		0x41 | 
|  | 386 | #define TSC10_RATE_80		0x42 | 
|  | 387 | #define TSC10_RATE_100		0x43 | 
|  | 388 | #define TSC10_RATE_130		0x44 | 
|  | 389 | #define TSC10_RATE_150		0x45 | 
|  | 390 |  | 
|  | 391 | /* commands */ | 
|  | 392 | #define TSC10_CMD_RESET		0x55 | 
|  | 393 | #define TSC10_CMD_RATE		0x05 | 
|  | 394 | #define TSC10_CMD_DATA1		0x01 | 
|  | 395 |  | 
|  | 396 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | 
|  | 397 | { | 
|  | 398 | struct usb_device *dev = usbtouch->udev; | 
|  | 399 | int ret; | 
|  | 400 | unsigned char buf[2]; | 
|  | 401 |  | 
|  | 402 | /* reset */ | 
|  | 403 | buf[0] = buf[1] = 0xFF; | 
|  | 404 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 405 | TSC10_CMD_RESET, | 
|  | 406 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 407 | 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 
|  | 408 | if (ret < 0) | 
|  | 409 | return ret; | 
|  | 410 | if (buf[0] != 0x06 || buf[1] != 0x00) | 
|  | 411 | return -ENODEV; | 
|  | 412 |  | 
|  | 413 | /* set coordinate output rate */ | 
|  | 414 | buf[0] = buf[1] = 0xFF; | 
|  | 415 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 416 | TSC10_CMD_RATE, | 
|  | 417 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 418 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 
|  | 419 | if (ret < 0) | 
|  | 420 | return ret; | 
| Daniel Ritz | 2a8281d | 2007-09-10 01:31:40 -0400 | [diff] [blame] | 421 | if ((buf[0] != 0x06 || buf[1] != 0x00) && | 
|  | 422 | (buf[0] != 0x15 || buf[1] != 0x01)) | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 423 | return -ENODEV; | 
|  | 424 |  | 
|  | 425 | /* start sending data */ | 
|  | 426 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 427 | TSC10_CMD_DATA1, | 
|  | 428 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 429 | 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 430 | if (ret < 0) | 
|  | 431 | return ret; | 
|  | 432 |  | 
|  | 433 | return 0; | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 437 | static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 438 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 439 | dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; | 
|  | 440 | dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; | 
|  | 441 | dev->touch = pkt[0] & 0x01; | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 442 |  | 
|  | 443 | return 1; | 
|  | 444 | } | 
|  | 445 | #endif | 
|  | 446 |  | 
|  | 447 |  | 
|  | 448 | /***************************************************************************** | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 449 | * IRTOUCH Part | 
|  | 450 | */ | 
|  | 451 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 452 | static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 453 | { | 
|  | 454 | dev->x = (pkt[3] << 8) | pkt[2]; | 
|  | 455 | dev->y = (pkt[5] << 8) | pkt[4]; | 
|  | 456 | dev->touch = (pkt[1] & 0x03) ? 1 : 0; | 
|  | 457 |  | 
|  | 458 | return 1; | 
|  | 459 | } | 
|  | 460 | #endif | 
|  | 461 |  | 
|  | 462 |  | 
|  | 463 | /***************************************************************************** | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 464 | * IdealTEK URTC1000 Part | 
|  | 465 | */ | 
|  | 466 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 467 | #ifndef MULTI_PACKET | 
|  | 468 | #define MULTI_PACKET | 
|  | 469 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 470 | static int idealtek_get_pkt_len(unsigned char *buf, int len) | 
|  | 471 | { | 
|  | 472 | if (buf[0] & 0x80) | 
|  | 473 | return 5; | 
|  | 474 | if (buf[0] == 0x01) | 
|  | 475 | return len; | 
|  | 476 | return 0; | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 480 | { | 
|  | 481 | switch (pkt[0] & 0x98) { | 
|  | 482 | case 0x88: | 
|  | 483 | /* touch data in IdealTEK mode */ | 
|  | 484 | dev->x = (pkt[1] << 5) | (pkt[2] >> 2); | 
|  | 485 | dev->y = (pkt[3] << 5) | (pkt[4] >> 2); | 
|  | 486 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | 
|  | 487 | return 1; | 
|  | 488 |  | 
|  | 489 | case 0x98: | 
|  | 490 | /* touch data in MT emulation mode */ | 
|  | 491 | dev->x = (pkt[2] << 5) | (pkt[1] >> 2); | 
|  | 492 | dev->y = (pkt[4] << 5) | (pkt[3] >> 2); | 
|  | 493 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | 
|  | 494 | return 1; | 
|  | 495 |  | 
|  | 496 | default: | 
|  | 497 | return 0; | 
|  | 498 | } | 
|  | 499 | } | 
|  | 500 | #endif | 
|  | 501 |  | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 502 | /***************************************************************************** | 
|  | 503 | * General Touch Part | 
|  | 504 | */ | 
|  | 505 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 506 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 507 | { | 
|  | 508 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; | 
|  | 509 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; | 
|  | 510 | dev->press = pkt[5] & 0xff; | 
|  | 511 | dev->touch = pkt[0] & 0x01; | 
|  | 512 |  | 
|  | 513 | return 1; | 
|  | 514 | } | 
|  | 515 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 516 |  | 
|  | 517 | /***************************************************************************** | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 518 | * GoTop Part | 
|  | 519 | */ | 
|  | 520 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 521 | static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 522 | { | 
|  | 523 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 
|  | 524 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 
|  | 525 | dev->touch = pkt[0] & 0x01; | 
|  | 526 | return 1; | 
|  | 527 | } | 
|  | 528 | #endif | 
|  | 529 |  | 
|  | 530 |  | 
|  | 531 | /***************************************************************************** | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 532 | * the different device descriptors | 
|  | 533 | */ | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 534 | #ifdef MULTI_PACKET | 
|  | 535 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | 
|  | 536 | unsigned char *pkt, int len); | 
|  | 537 | #endif | 
|  | 538 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 539 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 540 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 541 | [DEVTYPE_EGALAX] = { | 
|  | 542 | .min_xc		= 0x0, | 
|  | 543 | .max_xc		= 0x07ff, | 
|  | 544 | .min_yc		= 0x0, | 
|  | 545 | .max_yc		= 0x07ff, | 
|  | 546 | .rept_size	= 16, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 547 | .process_pkt	= usbtouch_process_multi, | 
|  | 548 | .get_pkt_len	= egalax_get_pkt_len, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 549 | .read_data	= egalax_read_data, | 
|  | 550 | }, | 
|  | 551 | #endif | 
|  | 552 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 553 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 554 | [DEVTYPE_PANJIT] = { | 
|  | 555 | .min_xc		= 0x0, | 
|  | 556 | .max_xc		= 0x0fff, | 
|  | 557 | .min_yc		= 0x0, | 
|  | 558 | .max_yc		= 0x0fff, | 
|  | 559 | .rept_size	= 8, | 
|  | 560 | .read_data	= panjit_read_data, | 
|  | 561 | }, | 
|  | 562 | #endif | 
|  | 563 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 564 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 565 | [DEVTYPE_3M] = { | 
|  | 566 | .min_xc		= 0x0, | 
|  | 567 | .max_xc		= 0x4000, | 
|  | 568 | .min_yc		= 0x0, | 
|  | 569 | .max_yc		= 0x4000, | 
|  | 570 | .rept_size	= 11, | 
|  | 571 | .read_data	= mtouch_read_data, | 
|  | 572 | .init		= mtouch_init, | 
|  | 573 | }, | 
|  | 574 | #endif | 
|  | 575 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 576 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 577 | [DEVTYPE_ITM] = { | 
|  | 578 | .min_xc		= 0x0, | 
|  | 579 | .max_xc		= 0x0fff, | 
|  | 580 | .min_yc		= 0x0, | 
|  | 581 | .max_yc		= 0x0fff, | 
|  | 582 | .max_press	= 0xff, | 
|  | 583 | .rept_size	= 8, | 
|  | 584 | .read_data	= itm_read_data, | 
|  | 585 | }, | 
|  | 586 | #endif | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 587 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 588 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 589 | [DEVTYPE_ETURBO] = { | 
|  | 590 | .min_xc		= 0x0, | 
|  | 591 | .max_xc		= 0x07ff, | 
|  | 592 | .min_yc		= 0x0, | 
|  | 593 | .max_yc		= 0x07ff, | 
|  | 594 | .rept_size	= 8, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 595 | .process_pkt	= usbtouch_process_multi, | 
|  | 596 | .get_pkt_len	= eturbo_get_pkt_len, | 
|  | 597 | .read_data	= eturbo_read_data, | 
|  | 598 | }, | 
|  | 599 | #endif | 
|  | 600 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 601 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 602 | [DEVTYPE_GUNZE] = { | 
|  | 603 | .min_xc		= 0x0, | 
|  | 604 | .max_xc		= 0x0fff, | 
|  | 605 | .min_yc		= 0x0, | 
|  | 606 | .max_yc		= 0x0fff, | 
|  | 607 | .rept_size	= 4, | 
|  | 608 | .read_data	= gunze_read_data, | 
|  | 609 | }, | 
|  | 610 | #endif | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 611 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 612 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 613 | [DEVTYPE_DMC_TSC10] = { | 
|  | 614 | .min_xc		= 0x0, | 
|  | 615 | .max_xc		= 0x03ff, | 
|  | 616 | .min_yc		= 0x0, | 
|  | 617 | .max_yc		= 0x03ff, | 
|  | 618 | .rept_size	= 5, | 
|  | 619 | .init		= dmc_tsc10_init, | 
|  | 620 | .read_data	= dmc_tsc10_read_data, | 
|  | 621 | }, | 
|  | 622 | #endif | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 623 |  | 
|  | 624 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 625 | [DEVTYPE_IRTOUCH] = { | 
|  | 626 | .min_xc		= 0x0, | 
|  | 627 | .max_xc		= 0x0fff, | 
|  | 628 | .min_yc		= 0x0, | 
|  | 629 | .max_yc		= 0x0fff, | 
|  | 630 | .rept_size	= 8, | 
|  | 631 | .read_data	= irtouch_read_data, | 
|  | 632 | }, | 
|  | 633 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 634 |  | 
|  | 635 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
|  | 636 | [DEVTYPE_IDEALTEK] = { | 
|  | 637 | .min_xc		= 0x0, | 
|  | 638 | .max_xc		= 0x0fff, | 
|  | 639 | .min_yc		= 0x0, | 
|  | 640 | .max_yc		= 0x0fff, | 
|  | 641 | .rept_size	= 8, | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 642 | .process_pkt	= usbtouch_process_multi, | 
|  | 643 | .get_pkt_len	= idealtek_get_pkt_len, | 
|  | 644 | .read_data	= idealtek_read_data, | 
|  | 645 | }, | 
|  | 646 | #endif | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 647 |  | 
|  | 648 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 649 | [DEVTYPE_GENERAL_TOUCH] = { | 
|  | 650 | .min_xc		= 0x0, | 
|  | 651 | .max_xc		= 0x0500, | 
|  | 652 | .min_yc		= 0x0, | 
|  | 653 | .max_yc		= 0x0500, | 
|  | 654 | .rept_size	= 7, | 
|  | 655 | .read_data	= general_touch_read_data, | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 656 | }, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 657 | #endif | 
|  | 658 |  | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 659 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 660 | [DEVTYPE_GOTOP] = { | 
|  | 661 | .min_xc		= 0x0, | 
|  | 662 | .max_xc		= 0x03ff, | 
|  | 663 | .min_yc		= 0x0, | 
|  | 664 | .max_yc		= 0x03ff, | 
|  | 665 | .rept_size	= 4, | 
|  | 666 | .read_data	= gotop_read_data, | 
|  | 667 | }, | 
|  | 668 | #endif | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 669 | }; | 
|  | 670 |  | 
|  | 671 |  | 
|  | 672 | /***************************************************************************** | 
|  | 673 | * Generic Part | 
|  | 674 | */ | 
|  | 675 | static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 676 | unsigned char *pkt, int len) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 677 | { | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 678 | struct usbtouch_device_info *type = usbtouch->type; | 
|  | 679 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 680 | if (!type->read_data(usbtouch, pkt)) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 681 | return; | 
|  | 682 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 683 | input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 684 |  | 
|  | 685 | if (swap_xy) { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 686 | input_report_abs(usbtouch->input, ABS_X, usbtouch->y); | 
|  | 687 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 688 | } else { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 689 | input_report_abs(usbtouch->input, ABS_X, usbtouch->x); | 
|  | 690 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 691 | } | 
|  | 692 | if (type->max_press) | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 693 | input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 694 | input_sync(usbtouch->input); | 
|  | 695 | } | 
|  | 696 |  | 
|  | 697 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 698 | #ifdef MULTI_PACKET | 
|  | 699 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 700 | unsigned char *pkt, int len) | 
|  | 701 | { | 
|  | 702 | unsigned char *buffer; | 
|  | 703 | int pkt_len, pos, buf_len, tmp; | 
|  | 704 |  | 
|  | 705 | /* process buffer */ | 
|  | 706 | if (unlikely(usbtouch->buf_len)) { | 
|  | 707 | /* try to get size */ | 
|  | 708 | pkt_len = usbtouch->type->get_pkt_len( | 
|  | 709 | usbtouch->buffer, usbtouch->buf_len); | 
|  | 710 |  | 
|  | 711 | /* drop? */ | 
|  | 712 | if (unlikely(!pkt_len)) | 
|  | 713 | goto out_flush_buf; | 
|  | 714 |  | 
|  | 715 | /* need to append -pkt_len bytes before able to get size */ | 
|  | 716 | if (unlikely(pkt_len < 0)) { | 
|  | 717 | int append = -pkt_len; | 
|  | 718 | if (unlikely(append > len)) | 
|  | 719 | append = len; | 
|  | 720 | if (usbtouch->buf_len + append >= usbtouch->type->rept_size) | 
|  | 721 | goto out_flush_buf; | 
|  | 722 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); | 
|  | 723 | usbtouch->buf_len += append; | 
|  | 724 |  | 
|  | 725 | pkt_len = usbtouch->type->get_pkt_len( | 
|  | 726 | usbtouch->buffer, usbtouch->buf_len); | 
|  | 727 | if (pkt_len < 0) | 
|  | 728 | return; | 
|  | 729 | } | 
|  | 730 |  | 
|  | 731 | /* append */ | 
|  | 732 | tmp = pkt_len - usbtouch->buf_len; | 
|  | 733 | if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) | 
|  | 734 | goto out_flush_buf; | 
|  | 735 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 736 | usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 737 |  | 
|  | 738 | buffer = pkt + tmp; | 
|  | 739 | buf_len = len - tmp; | 
|  | 740 | } else { | 
|  | 741 | buffer = pkt; | 
|  | 742 | buf_len = len; | 
|  | 743 | } | 
|  | 744 |  | 
|  | 745 | /* loop over the received packet, process */ | 
|  | 746 | pos = 0; | 
|  | 747 | while (pos < buf_len) { | 
|  | 748 | /* get packet len */ | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 749 | pkt_len = usbtouch->type->get_pkt_len(buffer + pos, | 
|  | 750 | buf_len - pos); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 751 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 752 | /* unknown packet: skip one byte */ | 
|  | 753 | if (unlikely(!pkt_len)) { | 
|  | 754 | pos++; | 
|  | 755 | continue; | 
|  | 756 | } | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 757 |  | 
|  | 758 | /* full packet: process */ | 
|  | 759 | if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 760 | usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 761 | } else { | 
|  | 762 | /* incomplete packet: save in buffer */ | 
|  | 763 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | 
|  | 764 | usbtouch->buf_len = buf_len - pos; | 
|  | 765 | return; | 
|  | 766 | } | 
|  | 767 | pos += pkt_len; | 
|  | 768 | } | 
|  | 769 |  | 
|  | 770 | out_flush_buf: | 
|  | 771 | usbtouch->buf_len = 0; | 
|  | 772 | return; | 
|  | 773 | } | 
|  | 774 | #endif | 
|  | 775 |  | 
|  | 776 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 777 | static void usbtouch_irq(struct urb *urb) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 778 | { | 
|  | 779 | struct usbtouch_usb *usbtouch = urb->context; | 
|  | 780 | int retval; | 
|  | 781 |  | 
|  | 782 | switch (urb->status) { | 
|  | 783 | case 0: | 
|  | 784 | /* success */ | 
|  | 785 | break; | 
| Pete Zaitcev | 38e2bfc | 2006-09-18 22:49:02 -0700 | [diff] [blame] | 786 | case -ETIME: | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 787 | /* this urb is timing out */ | 
|  | 788 | dbg("%s - urb timed out - was the device unplugged?", | 
|  | 789 | __FUNCTION__); | 
|  | 790 | return; | 
|  | 791 | case -ECONNRESET: | 
|  | 792 | case -ENOENT: | 
|  | 793 | case -ESHUTDOWN: | 
|  | 794 | /* this urb is terminated, clean up */ | 
|  | 795 | dbg("%s - urb shutting down with status: %d", | 
|  | 796 | __FUNCTION__, urb->status); | 
|  | 797 | return; | 
|  | 798 | default: | 
|  | 799 | dbg("%s - nonzero urb status received: %d", | 
|  | 800 | __FUNCTION__, urb->status); | 
|  | 801 | goto exit; | 
|  | 802 | } | 
|  | 803 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 804 | usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 805 |  | 
|  | 806 | exit: | 
|  | 807 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 
|  | 808 | if (retval) | 
|  | 809 | err("%s - usb_submit_urb failed with result: %d", | 
|  | 810 | __FUNCTION__, retval); | 
|  | 811 | } | 
|  | 812 |  | 
|  | 813 | static int usbtouch_open(struct input_dev *input) | 
|  | 814 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 815 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 816 |  | 
|  | 817 | usbtouch->irq->dev = usbtouch->udev; | 
|  | 818 |  | 
|  | 819 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | 
|  | 820 | return -EIO; | 
|  | 821 |  | 
|  | 822 | return 0; | 
|  | 823 | } | 
|  | 824 |  | 
|  | 825 | static void usbtouch_close(struct input_dev *input) | 
|  | 826 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 827 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 828 |  | 
|  | 829 | usb_kill_urb(usbtouch->irq); | 
|  | 830 | } | 
|  | 831 |  | 
|  | 832 |  | 
|  | 833 | static void usbtouch_free_buffers(struct usb_device *udev, | 
|  | 834 | struct usbtouch_usb *usbtouch) | 
|  | 835 | { | 
| Dmitry Torokhov | e37a97d | 2007-05-03 00:57:29 -0400 | [diff] [blame] | 836 | usb_buffer_free(udev, usbtouch->type->rept_size, | 
|  | 837 | usbtouch->data, usbtouch->data_dma); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 838 | kfree(usbtouch->buffer); | 
|  | 839 | } | 
|  | 840 |  | 
|  | 841 |  | 
|  | 842 | static int usbtouch_probe(struct usb_interface *intf, | 
|  | 843 | const struct usb_device_id *id) | 
|  | 844 | { | 
|  | 845 | struct usbtouch_usb *usbtouch; | 
|  | 846 | struct input_dev *input_dev; | 
|  | 847 | struct usb_host_interface *interface; | 
|  | 848 | struct usb_endpoint_descriptor *endpoint; | 
|  | 849 | struct usb_device *udev = interface_to_usbdev(intf); | 
|  | 850 | struct usbtouch_device_info *type; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 851 | int err = -ENOMEM; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 852 |  | 
|  | 853 | interface = intf->cur_altsetting; | 
|  | 854 | endpoint = &interface->endpoint[0].desc; | 
|  | 855 |  | 
|  | 856 | usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); | 
|  | 857 | input_dev = input_allocate_device(); | 
|  | 858 | if (!usbtouch || !input_dev) | 
|  | 859 | goto out_free; | 
|  | 860 |  | 
|  | 861 | type = &usbtouch_dev_info[id->driver_info]; | 
|  | 862 | usbtouch->type = type; | 
|  | 863 | if (!type->process_pkt) | 
|  | 864 | type->process_pkt = usbtouch_process_pkt; | 
|  | 865 |  | 
|  | 866 | usbtouch->data = usb_buffer_alloc(udev, type->rept_size, | 
| Christoph Lameter | e94b176 | 2006-12-06 20:33:17 -0800 | [diff] [blame] | 867 | GFP_KERNEL, &usbtouch->data_dma); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 868 | if (!usbtouch->data) | 
|  | 869 | goto out_free; | 
|  | 870 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 871 | if (type->get_pkt_len) { | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 872 | usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); | 
|  | 873 | if (!usbtouch->buffer) | 
|  | 874 | goto out_free_buffers; | 
|  | 875 | } | 
|  | 876 |  | 
|  | 877 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 
|  | 878 | if (!usbtouch->irq) { | 
|  | 879 | dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); | 
|  | 880 | goto out_free_buffers; | 
|  | 881 | } | 
|  | 882 |  | 
|  | 883 | usbtouch->udev = udev; | 
|  | 884 | usbtouch->input = input_dev; | 
|  | 885 |  | 
|  | 886 | if (udev->manufacturer) | 
|  | 887 | strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); | 
|  | 888 |  | 
|  | 889 | if (udev->product) { | 
|  | 890 | if (udev->manufacturer) | 
|  | 891 | strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); | 
|  | 892 | strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); | 
|  | 893 | } | 
|  | 894 |  | 
|  | 895 | if (!strlen(usbtouch->name)) | 
|  | 896 | snprintf(usbtouch->name, sizeof(usbtouch->name), | 
|  | 897 | "USB Touchscreen %04x:%04x", | 
|  | 898 | le16_to_cpu(udev->descriptor.idVendor), | 
|  | 899 | le16_to_cpu(udev->descriptor.idProduct)); | 
|  | 900 |  | 
|  | 901 | usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); | 
| Vladimir Shebordaev | 7b6dff9 | 2007-09-06 21:32:16 -0400 | [diff] [blame] | 902 | strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 903 |  | 
|  | 904 | input_dev->name = usbtouch->name; | 
|  | 905 | input_dev->phys = usbtouch->phys; | 
|  | 906 | usb_to_input_id(udev, &input_dev->id); | 
| Dmitry Torokhov | c0f82d5 | 2007-04-12 01:35:03 -0400 | [diff] [blame] | 907 | input_dev->dev.parent = &intf->dev; | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 908 |  | 
|  | 909 | input_set_drvdata(input_dev, usbtouch); | 
|  | 910 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 911 | input_dev->open = usbtouch_open; | 
|  | 912 | input_dev->close = usbtouch_close; | 
|  | 913 |  | 
| Jiri Slaby | 7b19ada | 2007-10-18 23:40:32 -0700 | [diff] [blame] | 914 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 
|  | 915 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 916 | input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); | 
|  | 917 | input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); | 
|  | 918 | if (type->max_press) | 
|  | 919 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, | 
|  | 920 | type->max_press, 0, 0); | 
|  | 921 |  | 
|  | 922 | usb_fill_int_urb(usbtouch->irq, usbtouch->udev, | 
| Daniel Ritz | d8fa59a | 2006-10-27 22:46:03 +0200 | [diff] [blame] | 923 | usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 924 | usbtouch->data, type->rept_size, | 
|  | 925 | usbtouch_irq, usbtouch, endpoint->bInterval); | 
|  | 926 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 927 | usbtouch->irq->dev = usbtouch->udev; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 928 | usbtouch->irq->transfer_dma = usbtouch->data_dma; | 
|  | 929 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 
|  | 930 |  | 
|  | 931 | /* device specific init */ | 
|  | 932 | if (type->init) { | 
|  | 933 | err = type->init(usbtouch); | 
|  | 934 | if (err) { | 
|  | 935 | dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); | 
|  | 936 | goto out_free_buffers; | 
|  | 937 | } | 
|  | 938 | } | 
|  | 939 |  | 
|  | 940 | err = input_register_device(usbtouch->input); | 
|  | 941 | if (err) { | 
|  | 942 | dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); | 
|  | 943 | goto out_free_buffers; | 
|  | 944 | } | 
|  | 945 |  | 
|  | 946 | usb_set_intfdata(intf, usbtouch); | 
|  | 947 |  | 
|  | 948 | return 0; | 
|  | 949 |  | 
|  | 950 | out_free_buffers: | 
|  | 951 | usbtouch_free_buffers(udev, usbtouch); | 
|  | 952 | out_free: | 
|  | 953 | input_free_device(input_dev); | 
|  | 954 | kfree(usbtouch); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 955 | return err; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 956 | } | 
|  | 957 |  | 
|  | 958 | static void usbtouch_disconnect(struct usb_interface *intf) | 
|  | 959 | { | 
|  | 960 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 
|  | 961 |  | 
|  | 962 | dbg("%s - called", __FUNCTION__); | 
|  | 963 |  | 
|  | 964 | if (!usbtouch) | 
|  | 965 | return; | 
|  | 966 |  | 
|  | 967 | dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); | 
|  | 968 | usb_set_intfdata(intf, NULL); | 
|  | 969 | usb_kill_urb(usbtouch->irq); | 
|  | 970 | input_unregister_device(usbtouch->input); | 
|  | 971 | usb_free_urb(usbtouch->irq); | 
|  | 972 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); | 
|  | 973 | kfree(usbtouch); | 
|  | 974 | } | 
|  | 975 |  | 
|  | 976 | MODULE_DEVICE_TABLE(usb, usbtouch_devices); | 
|  | 977 |  | 
|  | 978 | static struct usb_driver usbtouch_driver = { | 
|  | 979 | .name		= "usbtouchscreen", | 
|  | 980 | .probe		= usbtouch_probe, | 
|  | 981 | .disconnect	= usbtouch_disconnect, | 
|  | 982 | .id_table	= usbtouch_devices, | 
|  | 983 | }; | 
|  | 984 |  | 
|  | 985 | static int __init usbtouch_init(void) | 
|  | 986 | { | 
|  | 987 | return usb_register(&usbtouch_driver); | 
|  | 988 | } | 
|  | 989 |  | 
|  | 990 | static void __exit usbtouch_cleanup(void) | 
|  | 991 | { | 
|  | 992 | usb_deregister(&usbtouch_driver); | 
|  | 993 | } | 
|  | 994 |  | 
|  | 995 | module_init(usbtouch_init); | 
|  | 996 | module_exit(usbtouch_cleanup); | 
|  | 997 |  | 
|  | 998 | MODULE_AUTHOR(DRIVER_AUTHOR); | 
|  | 999 | MODULE_DESCRIPTION(DRIVER_DESC); | 
|  | 1000 | MODULE_LICENSE("GPL"); | 
|  | 1001 |  | 
|  | 1002 | MODULE_ALIAS("touchkitusb"); | 
|  | 1003 | MODULE_ALIAS("itmtouch"); | 
|  | 1004 | MODULE_ALIAS("mtouchusb"); |