1d05e84e6SDmitry Torokhov /****************************************************************************** 2d05e84e6SDmitry Torokhov * usbtouchscreen.c 3d05e84e6SDmitry Torokhov * Driver for USB Touchscreens, supporting those devices: 4d05e84e6SDmitry Torokhov * - eGalax Touchkit 5d05e84e6SDmitry Torokhov * includes eTurboTouch CT-410/510/700 6d05e84e6SDmitry Torokhov * - 3M/Microtouch EX II series 7d05e84e6SDmitry Torokhov * - ITM 8d05e84e6SDmitry Torokhov * - PanJit TouchSet 9d05e84e6SDmitry Torokhov * - eTurboTouch 10d05e84e6SDmitry Torokhov * - Gunze AHL61 11d05e84e6SDmitry Torokhov * - DMC TSC-10/25 12df561fcdSOndrej Zary * - IRTOUCHSYSTEMS/UNITOP 13a14a8401SOndrej Zary * - IdealTEK URTC1000 1462aa366dSDaniel Ritz * - General Touch 1514e40206SJerrold Jones * - GoTop Super_Q2/GogoPen/PenPower tablets 16d05e84e6SDmitry Torokhov * 1714e40206SJerrold Jones * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 18d05e84e6SDmitry Torokhov * Copyright (C) by Todd E. Johnson (mtouchusb.c) 19d05e84e6SDmitry Torokhov * 20d05e84e6SDmitry Torokhov * This program is free software; you can redistribute it and/or 21d05e84e6SDmitry Torokhov * modify it under the terms of the GNU General Public License as 22d05e84e6SDmitry Torokhov * published by the Free Software Foundation; either version 2 of the 23d05e84e6SDmitry Torokhov * License, or (at your option) any later version. 24d05e84e6SDmitry Torokhov * 25d05e84e6SDmitry Torokhov * This program is distributed in the hope that it will be useful, but 26d05e84e6SDmitry Torokhov * WITHOUT ANY WARRANTY; without even the implied warranty of 27d05e84e6SDmitry Torokhov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28d05e84e6SDmitry Torokhov * General Public License for more details. 29d05e84e6SDmitry Torokhov * 30d05e84e6SDmitry Torokhov * You should have received a copy of the GNU General Public License 31d05e84e6SDmitry Torokhov * along with this program; if not, write to the Free Software 32d05e84e6SDmitry Torokhov * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 33d05e84e6SDmitry Torokhov * 34d05e84e6SDmitry Torokhov * Driver is based on touchkitusb.c 35d05e84e6SDmitry Torokhov * - ITM parts are from itmtouch.c 36d05e84e6SDmitry Torokhov * - 3M parts are from mtouchusb.c 37d05e84e6SDmitry Torokhov * - PanJit parts are from an unmerged driver by Lanslott Gish 38d05e84e6SDmitry Torokhov * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged 39d05e84e6SDmitry Torokhov * driver from Marius Vollmer 40d05e84e6SDmitry Torokhov * 41d05e84e6SDmitry Torokhov *****************************************************************************/ 42d05e84e6SDmitry Torokhov 43d05e84e6SDmitry Torokhov //#define DEBUG 44d05e84e6SDmitry Torokhov 45d05e84e6SDmitry Torokhov #include <linux/kernel.h> 46d05e84e6SDmitry Torokhov #include <linux/slab.h> 47d05e84e6SDmitry Torokhov #include <linux/input.h> 48d05e84e6SDmitry Torokhov #include <linux/module.h> 49d05e84e6SDmitry Torokhov #include <linux/init.h> 50d05e84e6SDmitry Torokhov #include <linux/usb.h> 51d05e84e6SDmitry Torokhov #include <linux/usb/input.h> 52ec42d448SDaniel Ritz #include <linux/hid.h> 53d05e84e6SDmitry Torokhov 54d05e84e6SDmitry Torokhov 5562aa366dSDaniel Ritz #define DRIVER_VERSION "v0.6" 56d05e84e6SDmitry Torokhov #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 57d05e84e6SDmitry Torokhov #define DRIVER_DESC "USB Touchscreen Driver" 58d05e84e6SDmitry Torokhov 59d05e84e6SDmitry Torokhov static int swap_xy; 60d05e84e6SDmitry Torokhov module_param(swap_xy, bool, 0644); 61d05e84e6SDmitry Torokhov MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 62d05e84e6SDmitry Torokhov 63*c9cbf3d3SDan Streetman static int hwcalib_xy; 64*c9cbf3d3SDan Streetman module_param(hwcalib_xy, bool, 0644); 65*c9cbf3d3SDan Streetman MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); 66*c9cbf3d3SDan Streetman 67d05e84e6SDmitry Torokhov /* device specifc data/functions */ 68d05e84e6SDmitry Torokhov struct usbtouch_usb; 69d05e84e6SDmitry Torokhov struct usbtouch_device_info { 70d05e84e6SDmitry Torokhov int min_xc, max_xc; 71d05e84e6SDmitry Torokhov int min_yc, max_yc; 72d05e84e6SDmitry Torokhov int min_press, max_press; 73d05e84e6SDmitry Torokhov int rept_size; 74d05e84e6SDmitry Torokhov 75d05e84e6SDmitry Torokhov void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); 7662aa366dSDaniel Ritz 7762aa366dSDaniel Ritz /* 7862aa366dSDaniel Ritz * used to get the packet len. possible return values: 7962aa366dSDaniel Ritz * > 0: packet len 8062aa366dSDaniel Ritz * = 0: skip one byte 8162aa366dSDaniel Ritz * < 0: -return value more bytes needed 8262aa366dSDaniel Ritz */ 83d05e84e6SDmitry Torokhov int (*get_pkt_len) (unsigned char *pkt, int len); 8462aa366dSDaniel Ritz 85d05e84e6SDmitry Torokhov int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); 86d05e84e6SDmitry Torokhov int (*init) (struct usbtouch_usb *usbtouch); 87d05e84e6SDmitry Torokhov }; 88d05e84e6SDmitry Torokhov 89d05e84e6SDmitry Torokhov /* a usbtouch device */ 90d05e84e6SDmitry Torokhov struct usbtouch_usb { 91d05e84e6SDmitry Torokhov unsigned char *data; 92d05e84e6SDmitry Torokhov dma_addr_t data_dma; 93d05e84e6SDmitry Torokhov unsigned char *buffer; 94d05e84e6SDmitry Torokhov int buf_len; 95d05e84e6SDmitry Torokhov struct urb *irq; 96d05e84e6SDmitry Torokhov struct usb_device *udev; 97d05e84e6SDmitry Torokhov struct input_dev *input; 98d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 99d05e84e6SDmitry Torokhov char name[128]; 100d05e84e6SDmitry Torokhov char phys[64]; 101d05e84e6SDmitry Torokhov 102d05e84e6SDmitry Torokhov int x, y; 103d05e84e6SDmitry Torokhov int touch, press; 104d05e84e6SDmitry Torokhov }; 105d05e84e6SDmitry Torokhov 106d05e84e6SDmitry Torokhov 107d05e84e6SDmitry Torokhov /* device types */ 108d05e84e6SDmitry Torokhov enum { 109ec42d448SDaniel Ritz DEVTYPE_IGNORE = -1, 110d05e84e6SDmitry Torokhov DEVTYPE_EGALAX, 111d05e84e6SDmitry Torokhov DEVTYPE_PANJIT, 112d05e84e6SDmitry Torokhov DEVTYPE_3M, 113d05e84e6SDmitry Torokhov DEVTYPE_ITM, 114d05e84e6SDmitry Torokhov DEVTYPE_ETURBO, 115d05e84e6SDmitry Torokhov DEVTYPE_GUNZE, 116d05e84e6SDmitry Torokhov DEVTYPE_DMC_TSC10, 117df561fcdSOndrej Zary DEVTYPE_IRTOUCH, 118a14a8401SOndrej Zary DEVTYPE_IDEALTEK, 1199d5657dbSIlya Frolov DEVTYPE_GENERAL_TOUCH, 12014e40206SJerrold Jones DEVTYPE_GOTOP, 121d05e84e6SDmitry Torokhov }; 122d05e84e6SDmitry Torokhov 123ec42d448SDaniel Ritz #define USB_DEVICE_HID_CLASS(vend, prod) \ 124ec42d448SDaniel Ritz .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ 125ec42d448SDaniel Ritz | USB_DEVICE_ID_MATCH_DEVICE, \ 126ec42d448SDaniel Ritz .idVendor = (vend), \ 127ec42d448SDaniel Ritz .idProduct = (prod), \ 128ec42d448SDaniel Ritz .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 129ec42d448SDaniel Ritz .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE 130ec42d448SDaniel Ritz 131d05e84e6SDmitry Torokhov static struct usb_device_id usbtouch_devices[] = { 132c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 133ec42d448SDaniel Ritz /* ignore the HID capable devices, handled by usbhid */ 134ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 135ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 136ec42d448SDaniel Ritz 137ec42d448SDaniel Ritz /* normal device IDs */ 138d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 139d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 140d05e84e6SDmitry Torokhov {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 141d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 142d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 143d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 144d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 145d05e84e6SDmitry Torokhov #endif 146d05e84e6SDmitry Torokhov 147c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 148d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 149d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 150d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 151d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 152d05e84e6SDmitry Torokhov #endif 153d05e84e6SDmitry Torokhov 154c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 155d05e84e6SDmitry Torokhov {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 156d05e84e6SDmitry Torokhov #endif 157d05e84e6SDmitry Torokhov 158c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 159d05e84e6SDmitry Torokhov {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 160d05e84e6SDmitry Torokhov #endif 161d05e84e6SDmitry Torokhov 162c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 163d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 164d05e84e6SDmitry Torokhov #endif 165d05e84e6SDmitry Torokhov 166c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 167d05e84e6SDmitry Torokhov {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 168d05e84e6SDmitry Torokhov #endif 169d05e84e6SDmitry Torokhov 170c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 171d05e84e6SDmitry Torokhov {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 172d05e84e6SDmitry Torokhov #endif 173d05e84e6SDmitry Torokhov 174df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 175df561fcdSOndrej Zary {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 176df561fcdSOndrej Zary {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 177df561fcdSOndrej Zary #endif 178df561fcdSOndrej Zary 179a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 180a14a8401SOndrej Zary {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 181a14a8401SOndrej Zary #endif 182a14a8401SOndrej Zary 1839d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 1849d5657dbSIlya Frolov {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 1859d5657dbSIlya Frolov #endif 1869d5657dbSIlya Frolov 18714e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 18814e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 18914e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 19014e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 19114e40206SJerrold Jones #endif 19214e40206SJerrold Jones 193d05e84e6SDmitry Torokhov {} 194d05e84e6SDmitry Torokhov }; 195d05e84e6SDmitry Torokhov 196d05e84e6SDmitry Torokhov 197d05e84e6SDmitry Torokhov /***************************************************************************** 198d05e84e6SDmitry Torokhov * eGalax part 199d05e84e6SDmitry Torokhov */ 200d05e84e6SDmitry Torokhov 201c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 202d05e84e6SDmitry Torokhov 20362aa366dSDaniel Ritz #ifndef MULTI_PACKET 20462aa366dSDaniel Ritz #define MULTI_PACKET 20562aa366dSDaniel Ritz #endif 20662aa366dSDaniel Ritz 207d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK 0xFE 208d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT 0x80 209d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG 0x0A 210d05e84e6SDmitry Torokhov 211d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 212d05e84e6SDmitry Torokhov { 213d05e84e6SDmitry Torokhov if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 214d05e84e6SDmitry Torokhov return 0; 215d05e84e6SDmitry Torokhov 216d05e84e6SDmitry Torokhov dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 217d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 218d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 219d05e84e6SDmitry Torokhov 220d05e84e6SDmitry Torokhov return 1; 221d05e84e6SDmitry Torokhov } 222d05e84e6SDmitry Torokhov 223d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len) 224d05e84e6SDmitry Torokhov { 225d05e84e6SDmitry Torokhov switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 226d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_REPT: 227d05e84e6SDmitry Torokhov return 5; 228d05e84e6SDmitry Torokhov 229d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_DIAG: 230d05e84e6SDmitry Torokhov if (len < 2) 231d05e84e6SDmitry Torokhov return -1; 232d05e84e6SDmitry Torokhov 233d05e84e6SDmitry Torokhov return buf[1] + 2; 234d05e84e6SDmitry Torokhov } 235d05e84e6SDmitry Torokhov 236d05e84e6SDmitry Torokhov return 0; 237d05e84e6SDmitry Torokhov } 238d05e84e6SDmitry Torokhov #endif 239d05e84e6SDmitry Torokhov 240d05e84e6SDmitry Torokhov 241d05e84e6SDmitry Torokhov /***************************************************************************** 242d05e84e6SDmitry Torokhov * PanJit Part 243d05e84e6SDmitry Torokhov */ 244c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 245d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 246d05e84e6SDmitry Torokhov { 247d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 248d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 249d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 250d05e84e6SDmitry Torokhov 251d05e84e6SDmitry Torokhov return 1; 252d05e84e6SDmitry Torokhov } 253d05e84e6SDmitry Torokhov #endif 254d05e84e6SDmitry Torokhov 255d05e84e6SDmitry Torokhov 256d05e84e6SDmitry Torokhov /***************************************************************************** 257d05e84e6SDmitry Torokhov * 3M/Microtouch Part 258d05e84e6SDmitry Torokhov */ 259c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 260d05e84e6SDmitry Torokhov 261d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT 1 262d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET 7 263d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID 10 264d05e84e6SDmitry Torokhov 265d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 266d05e84e6SDmitry Torokhov { 267*c9cbf3d3SDan Streetman if (hwcalib_xy) { 268*c9cbf3d3SDan Streetman dev->x = (pkt[4] << 8) | pkt[3]; 269*c9cbf3d3SDan Streetman dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 270*c9cbf3d3SDan Streetman } else { 271d05e84e6SDmitry Torokhov dev->x = (pkt[8] << 8) | pkt[7]; 272d05e84e6SDmitry Torokhov dev->y = (pkt[10] << 8) | pkt[9]; 273*c9cbf3d3SDan Streetman } 274d05e84e6SDmitry Torokhov dev->touch = (pkt[2] & 0x40) ? 1 : 0; 275d05e84e6SDmitry Torokhov 276d05e84e6SDmitry Torokhov return 1; 277d05e84e6SDmitry Torokhov } 278d05e84e6SDmitry Torokhov 279d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch) 280d05e84e6SDmitry Torokhov { 281d05e84e6SDmitry Torokhov int ret, i; 282d05e84e6SDmitry Torokhov 283d05e84e6SDmitry Torokhov ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 284d05e84e6SDmitry Torokhov MTOUCHUSB_RESET, 285d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 286d05e84e6SDmitry Torokhov 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 287d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", 288ea3e6c59SHarvey Harrison __func__, ret); 289d05e84e6SDmitry Torokhov if (ret < 0) 290d05e84e6SDmitry Torokhov return ret; 291d05e84e6SDmitry Torokhov msleep(150); 292d05e84e6SDmitry Torokhov 293d05e84e6SDmitry Torokhov for (i = 0; i < 3; i++) { 294d05e84e6SDmitry Torokhov ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 295d05e84e6SDmitry Torokhov MTOUCHUSB_ASYNC_REPORT, 296d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 297d05e84e6SDmitry Torokhov 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 298d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", 299ea3e6c59SHarvey Harrison __func__, ret); 300d05e84e6SDmitry Torokhov if (ret >= 0) 301d05e84e6SDmitry Torokhov break; 302d05e84e6SDmitry Torokhov if (ret != -EPIPE) 303d05e84e6SDmitry Torokhov return ret; 304d05e84e6SDmitry Torokhov } 305d05e84e6SDmitry Torokhov 306*c9cbf3d3SDan Streetman /* Default min/max xy are the raw values, override if using hw-calib */ 307*c9cbf3d3SDan Streetman if (hwcalib_xy) { 308*c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 309*c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 310*c9cbf3d3SDan Streetman } 311*c9cbf3d3SDan Streetman 312d05e84e6SDmitry Torokhov return 0; 313d05e84e6SDmitry Torokhov } 314d05e84e6SDmitry Torokhov #endif 315d05e84e6SDmitry Torokhov 316d05e84e6SDmitry Torokhov 317d05e84e6SDmitry Torokhov /***************************************************************************** 318d05e84e6SDmitry Torokhov * ITM Part 319d05e84e6SDmitry Torokhov */ 320c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 321d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 322d05e84e6SDmitry Torokhov { 323d05e84e6SDmitry Torokhov int touch; 324d05e84e6SDmitry Torokhov /* 325d05e84e6SDmitry Torokhov * ITM devices report invalid x/y data if not touched. 326d05e84e6SDmitry Torokhov * if the screen was touched before but is not touched any more 327d05e84e6SDmitry Torokhov * report touch as 0 with the last valid x/y data once. then stop 328d05e84e6SDmitry Torokhov * reporting data until touched again. 329d05e84e6SDmitry Torokhov */ 330d05e84e6SDmitry Torokhov dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 331d05e84e6SDmitry Torokhov 332d05e84e6SDmitry Torokhov touch = ~pkt[7] & 0x20; 333d05e84e6SDmitry Torokhov if (!touch) { 334d05e84e6SDmitry Torokhov if (dev->touch) { 335d05e84e6SDmitry Torokhov dev->touch = 0; 336d05e84e6SDmitry Torokhov return 1; 337d05e84e6SDmitry Torokhov } 338d05e84e6SDmitry Torokhov 339d05e84e6SDmitry Torokhov return 0; 340d05e84e6SDmitry Torokhov } 341d05e84e6SDmitry Torokhov 342d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 343d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 344d05e84e6SDmitry Torokhov dev->touch = touch; 345d05e84e6SDmitry Torokhov 346d05e84e6SDmitry Torokhov return 1; 347d05e84e6SDmitry Torokhov } 348d05e84e6SDmitry Torokhov #endif 349d05e84e6SDmitry Torokhov 350d05e84e6SDmitry Torokhov 351d05e84e6SDmitry Torokhov /***************************************************************************** 352d05e84e6SDmitry Torokhov * eTurboTouch part 353d05e84e6SDmitry Torokhov */ 354c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 35562aa366dSDaniel Ritz #ifndef MULTI_PACKET 35662aa366dSDaniel Ritz #define MULTI_PACKET 35762aa366dSDaniel Ritz #endif 358d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 359d05e84e6SDmitry Torokhov { 360d05e84e6SDmitry Torokhov unsigned int shift; 361d05e84e6SDmitry Torokhov 362d05e84e6SDmitry Torokhov /* packets should start with sync */ 363d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80)) 364d05e84e6SDmitry Torokhov return 0; 365d05e84e6SDmitry Torokhov 366d05e84e6SDmitry Torokhov shift = (6 - (pkt[0] & 0x03)); 367d05e84e6SDmitry Torokhov dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 368d05e84e6SDmitry Torokhov dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 369d05e84e6SDmitry Torokhov dev->touch = (pkt[0] & 0x10) ? 1 : 0; 370d05e84e6SDmitry Torokhov 371d05e84e6SDmitry Torokhov return 1; 372d05e84e6SDmitry Torokhov } 373d05e84e6SDmitry Torokhov 374d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len) 375d05e84e6SDmitry Torokhov { 376d05e84e6SDmitry Torokhov if (buf[0] & 0x80) 377d05e84e6SDmitry Torokhov return 5; 378d05e84e6SDmitry Torokhov if (buf[0] == 0x01) 379d05e84e6SDmitry Torokhov return 3; 380d05e84e6SDmitry Torokhov return 0; 381d05e84e6SDmitry Torokhov } 382d05e84e6SDmitry Torokhov #endif 383d05e84e6SDmitry Torokhov 384d05e84e6SDmitry Torokhov 385d05e84e6SDmitry Torokhov /***************************************************************************** 386d05e84e6SDmitry Torokhov * Gunze part 387d05e84e6SDmitry Torokhov */ 388c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 389d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 390d05e84e6SDmitry Torokhov { 391d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 392d05e84e6SDmitry Torokhov return 0; 393d05e84e6SDmitry Torokhov 394d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 395d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 396d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x20; 397d05e84e6SDmitry Torokhov 398d05e84e6SDmitry Torokhov return 1; 399d05e84e6SDmitry Torokhov } 400d05e84e6SDmitry Torokhov #endif 401d05e84e6SDmitry Torokhov 402d05e84e6SDmitry Torokhov /***************************************************************************** 403d05e84e6SDmitry Torokhov * DMC TSC-10/25 Part 404d05e84e6SDmitry Torokhov * 405d05e84e6SDmitry Torokhov * Documentation about the controller and it's protocol can be found at 406d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 407d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 408d05e84e6SDmitry Torokhov */ 409c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 410d05e84e6SDmitry Torokhov 411d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */ 412d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT 0x50 413d05e84e6SDmitry Torokhov #define TSC10_RATE_30 0x40 414d05e84e6SDmitry Torokhov #define TSC10_RATE_50 0x41 415d05e84e6SDmitry Torokhov #define TSC10_RATE_80 0x42 416d05e84e6SDmitry Torokhov #define TSC10_RATE_100 0x43 417d05e84e6SDmitry Torokhov #define TSC10_RATE_130 0x44 418d05e84e6SDmitry Torokhov #define TSC10_RATE_150 0x45 419d05e84e6SDmitry Torokhov 420d05e84e6SDmitry Torokhov /* commands */ 421d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET 0x55 422d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE 0x05 423d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1 0x01 424d05e84e6SDmitry Torokhov 425d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 426d05e84e6SDmitry Torokhov { 427d05e84e6SDmitry Torokhov struct usb_device *dev = usbtouch->udev; 42876d057ceSOliver Neukum int ret = -ENOMEM; 42976d057ceSOliver Neukum unsigned char *buf; 430d05e84e6SDmitry Torokhov 43176d057ceSOliver Neukum buf = kmalloc(2, GFP_KERNEL); 43276d057ceSOliver Neukum if (!buf) 43376d057ceSOliver Neukum goto err_nobuf; 434d05e84e6SDmitry Torokhov /* reset */ 435d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 436d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 437d05e84e6SDmitry Torokhov TSC10_CMD_RESET, 438d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 439d05e84e6SDmitry Torokhov 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 440d05e84e6SDmitry Torokhov if (ret < 0) 44176d057ceSOliver Neukum goto err_out; 4422ec6f246SNuno Lucas if (buf[0] != 0x06) { 44376d057ceSOliver Neukum ret = -ENODEV; 44476d057ceSOliver Neukum goto err_out; 44576d057ceSOliver Neukum } 446d05e84e6SDmitry Torokhov 447d05e84e6SDmitry Torokhov /* set coordinate output rate */ 448d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 449d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 450d05e84e6SDmitry Torokhov TSC10_CMD_RATE, 451d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 452d05e84e6SDmitry Torokhov TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 453d05e84e6SDmitry Torokhov if (ret < 0) 45476d057ceSOliver Neukum goto err_out; 4552ec6f246SNuno Lucas if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 45676d057ceSOliver Neukum ret = -ENODEV; 45776d057ceSOliver Neukum goto err_out; 45876d057ceSOliver Neukum } 459d05e84e6SDmitry Torokhov 460d05e84e6SDmitry Torokhov /* start sending data */ 461d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 462d05e84e6SDmitry Torokhov TSC10_CMD_DATA1, 463d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 464d05e84e6SDmitry Torokhov 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 46576d057ceSOliver Neukum err_out: 46676d057ceSOliver Neukum kfree(buf); 46776d057ceSOliver Neukum err_nobuf: 468d05e84e6SDmitry Torokhov return ret; 469d05e84e6SDmitry Torokhov } 470d05e84e6SDmitry Torokhov 471d05e84e6SDmitry Torokhov 472d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 473d05e84e6SDmitry Torokhov { 474d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 475d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 476d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 477d05e84e6SDmitry Torokhov 478d05e84e6SDmitry Torokhov return 1; 479d05e84e6SDmitry Torokhov } 480d05e84e6SDmitry Torokhov #endif 481d05e84e6SDmitry Torokhov 482d05e84e6SDmitry Torokhov 483d05e84e6SDmitry Torokhov /***************************************************************************** 484df561fcdSOndrej Zary * IRTOUCH Part 485df561fcdSOndrej Zary */ 486df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 487df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 488df561fcdSOndrej Zary { 489df561fcdSOndrej Zary dev->x = (pkt[3] << 8) | pkt[2]; 490df561fcdSOndrej Zary dev->y = (pkt[5] << 8) | pkt[4]; 491df561fcdSOndrej Zary dev->touch = (pkt[1] & 0x03) ? 1 : 0; 492df561fcdSOndrej Zary 493df561fcdSOndrej Zary return 1; 494df561fcdSOndrej Zary } 495df561fcdSOndrej Zary #endif 496df561fcdSOndrej Zary 497df561fcdSOndrej Zary 498df561fcdSOndrej Zary /***************************************************************************** 499a14a8401SOndrej Zary * IdealTEK URTC1000 Part 500a14a8401SOndrej Zary */ 501a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 50262aa366dSDaniel Ritz #ifndef MULTI_PACKET 50362aa366dSDaniel Ritz #define MULTI_PACKET 50462aa366dSDaniel Ritz #endif 505a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len) 506a14a8401SOndrej Zary { 507a14a8401SOndrej Zary if (buf[0] & 0x80) 508a14a8401SOndrej Zary return 5; 509a14a8401SOndrej Zary if (buf[0] == 0x01) 510a14a8401SOndrej Zary return len; 511a14a8401SOndrej Zary return 0; 512a14a8401SOndrej Zary } 513a14a8401SOndrej Zary 514a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 515a14a8401SOndrej Zary { 516a14a8401SOndrej Zary switch (pkt[0] & 0x98) { 517a14a8401SOndrej Zary case 0x88: 518a14a8401SOndrej Zary /* touch data in IdealTEK mode */ 519a14a8401SOndrej Zary dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 520a14a8401SOndrej Zary dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 521a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 522a14a8401SOndrej Zary return 1; 523a14a8401SOndrej Zary 524a14a8401SOndrej Zary case 0x98: 525a14a8401SOndrej Zary /* touch data in MT emulation mode */ 526a14a8401SOndrej Zary dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 527a14a8401SOndrej Zary dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 528a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 529a14a8401SOndrej Zary return 1; 530a14a8401SOndrej Zary 531a14a8401SOndrej Zary default: 532a14a8401SOndrej Zary return 0; 533a14a8401SOndrej Zary } 534a14a8401SOndrej Zary } 535a14a8401SOndrej Zary #endif 536a14a8401SOndrej Zary 5379d5657dbSIlya Frolov /***************************************************************************** 5389d5657dbSIlya Frolov * General Touch Part 5399d5657dbSIlya Frolov */ 5409d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 5419d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 5429d5657dbSIlya Frolov { 5439d5657dbSIlya Frolov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; 5449d5657dbSIlya Frolov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; 5459d5657dbSIlya Frolov dev->press = pkt[5] & 0xff; 5469d5657dbSIlya Frolov dev->touch = pkt[0] & 0x01; 5479d5657dbSIlya Frolov 5489d5657dbSIlya Frolov return 1; 5499d5657dbSIlya Frolov } 5509d5657dbSIlya Frolov #endif 551a14a8401SOndrej Zary 552a14a8401SOndrej Zary /***************************************************************************** 55314e40206SJerrold Jones * GoTop Part 55414e40206SJerrold Jones */ 55514e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 55614e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 55714e40206SJerrold Jones { 55814e40206SJerrold Jones dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 55914e40206SJerrold Jones dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 56014e40206SJerrold Jones dev->touch = pkt[0] & 0x01; 56114e40206SJerrold Jones return 1; 56214e40206SJerrold Jones } 56314e40206SJerrold Jones #endif 56414e40206SJerrold Jones 56514e40206SJerrold Jones 56614e40206SJerrold Jones /***************************************************************************** 567d05e84e6SDmitry Torokhov * the different device descriptors 568d05e84e6SDmitry Torokhov */ 56962aa366dSDaniel Ritz #ifdef MULTI_PACKET 57062aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 57162aa366dSDaniel Ritz unsigned char *pkt, int len); 57262aa366dSDaniel Ritz #endif 57362aa366dSDaniel Ritz 574d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = { 575c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 576d05e84e6SDmitry Torokhov [DEVTYPE_EGALAX] = { 577d05e84e6SDmitry Torokhov .min_xc = 0x0, 578d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 579d05e84e6SDmitry Torokhov .min_yc = 0x0, 580d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 581d05e84e6SDmitry Torokhov .rept_size = 16, 582d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 583d05e84e6SDmitry Torokhov .get_pkt_len = egalax_get_pkt_len, 584d05e84e6SDmitry Torokhov .read_data = egalax_read_data, 585d05e84e6SDmitry Torokhov }, 586d05e84e6SDmitry Torokhov #endif 587d05e84e6SDmitry Torokhov 588c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 589d05e84e6SDmitry Torokhov [DEVTYPE_PANJIT] = { 590d05e84e6SDmitry Torokhov .min_xc = 0x0, 591d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 592d05e84e6SDmitry Torokhov .min_yc = 0x0, 593d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 594d05e84e6SDmitry Torokhov .rept_size = 8, 595d05e84e6SDmitry Torokhov .read_data = panjit_read_data, 596d05e84e6SDmitry Torokhov }, 597d05e84e6SDmitry Torokhov #endif 598d05e84e6SDmitry Torokhov 599c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 600d05e84e6SDmitry Torokhov [DEVTYPE_3M] = { 601d05e84e6SDmitry Torokhov .min_xc = 0x0, 602d05e84e6SDmitry Torokhov .max_xc = 0x4000, 603d05e84e6SDmitry Torokhov .min_yc = 0x0, 604d05e84e6SDmitry Torokhov .max_yc = 0x4000, 605d05e84e6SDmitry Torokhov .rept_size = 11, 606d05e84e6SDmitry Torokhov .read_data = mtouch_read_data, 607d05e84e6SDmitry Torokhov .init = mtouch_init, 608d05e84e6SDmitry Torokhov }, 609d05e84e6SDmitry Torokhov #endif 610d05e84e6SDmitry Torokhov 611c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 612d05e84e6SDmitry Torokhov [DEVTYPE_ITM] = { 613d05e84e6SDmitry Torokhov .min_xc = 0x0, 614d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 615d05e84e6SDmitry Torokhov .min_yc = 0x0, 616d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 617d05e84e6SDmitry Torokhov .max_press = 0xff, 618d05e84e6SDmitry Torokhov .rept_size = 8, 619d05e84e6SDmitry Torokhov .read_data = itm_read_data, 620d05e84e6SDmitry Torokhov }, 621d05e84e6SDmitry Torokhov #endif 622d05e84e6SDmitry Torokhov 623c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 624d05e84e6SDmitry Torokhov [DEVTYPE_ETURBO] = { 625d05e84e6SDmitry Torokhov .min_xc = 0x0, 626d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 627d05e84e6SDmitry Torokhov .min_yc = 0x0, 628d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 629d05e84e6SDmitry Torokhov .rept_size = 8, 630d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 631d05e84e6SDmitry Torokhov .get_pkt_len = eturbo_get_pkt_len, 632d05e84e6SDmitry Torokhov .read_data = eturbo_read_data, 633d05e84e6SDmitry Torokhov }, 634d05e84e6SDmitry Torokhov #endif 635d05e84e6SDmitry Torokhov 636c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 637d05e84e6SDmitry Torokhov [DEVTYPE_GUNZE] = { 638d05e84e6SDmitry Torokhov .min_xc = 0x0, 639d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 640d05e84e6SDmitry Torokhov .min_yc = 0x0, 641d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 642d05e84e6SDmitry Torokhov .rept_size = 4, 643d05e84e6SDmitry Torokhov .read_data = gunze_read_data, 644d05e84e6SDmitry Torokhov }, 645d05e84e6SDmitry Torokhov #endif 646d05e84e6SDmitry Torokhov 647c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 648d05e84e6SDmitry Torokhov [DEVTYPE_DMC_TSC10] = { 649d05e84e6SDmitry Torokhov .min_xc = 0x0, 650d05e84e6SDmitry Torokhov .max_xc = 0x03ff, 651d05e84e6SDmitry Torokhov .min_yc = 0x0, 652d05e84e6SDmitry Torokhov .max_yc = 0x03ff, 653d05e84e6SDmitry Torokhov .rept_size = 5, 654d05e84e6SDmitry Torokhov .init = dmc_tsc10_init, 655d05e84e6SDmitry Torokhov .read_data = dmc_tsc10_read_data, 656d05e84e6SDmitry Torokhov }, 657d05e84e6SDmitry Torokhov #endif 658df561fcdSOndrej Zary 659df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 660df561fcdSOndrej Zary [DEVTYPE_IRTOUCH] = { 661df561fcdSOndrej Zary .min_xc = 0x0, 662df561fcdSOndrej Zary .max_xc = 0x0fff, 663df561fcdSOndrej Zary .min_yc = 0x0, 664df561fcdSOndrej Zary .max_yc = 0x0fff, 665df561fcdSOndrej Zary .rept_size = 8, 666df561fcdSOndrej Zary .read_data = irtouch_read_data, 667df561fcdSOndrej Zary }, 668df561fcdSOndrej Zary #endif 669a14a8401SOndrej Zary 670a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 671a14a8401SOndrej Zary [DEVTYPE_IDEALTEK] = { 672a14a8401SOndrej Zary .min_xc = 0x0, 673a14a8401SOndrej Zary .max_xc = 0x0fff, 674a14a8401SOndrej Zary .min_yc = 0x0, 675a14a8401SOndrej Zary .max_yc = 0x0fff, 676a14a8401SOndrej Zary .rept_size = 8, 677a14a8401SOndrej Zary .process_pkt = usbtouch_process_multi, 678a14a8401SOndrej Zary .get_pkt_len = idealtek_get_pkt_len, 679a14a8401SOndrej Zary .read_data = idealtek_read_data, 680a14a8401SOndrej Zary }, 681a14a8401SOndrej Zary #endif 6829d5657dbSIlya Frolov 6839d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 6849d5657dbSIlya Frolov [DEVTYPE_GENERAL_TOUCH] = { 6859d5657dbSIlya Frolov .min_xc = 0x0, 6869d5657dbSIlya Frolov .max_xc = 0x0500, 6879d5657dbSIlya Frolov .min_yc = 0x0, 6889d5657dbSIlya Frolov .max_yc = 0x0500, 6899d5657dbSIlya Frolov .rept_size = 7, 6909d5657dbSIlya Frolov .read_data = general_touch_read_data, 69114e40206SJerrold Jones }, 6929d5657dbSIlya Frolov #endif 6939d5657dbSIlya Frolov 69414e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 69514e40206SJerrold Jones [DEVTYPE_GOTOP] = { 69614e40206SJerrold Jones .min_xc = 0x0, 69714e40206SJerrold Jones .max_xc = 0x03ff, 69814e40206SJerrold Jones .min_yc = 0x0, 69914e40206SJerrold Jones .max_yc = 0x03ff, 70014e40206SJerrold Jones .rept_size = 4, 70114e40206SJerrold Jones .read_data = gotop_read_data, 70214e40206SJerrold Jones }, 70314e40206SJerrold Jones #endif 704d05e84e6SDmitry Torokhov }; 705d05e84e6SDmitry Torokhov 706d05e84e6SDmitry Torokhov 707d05e84e6SDmitry Torokhov /***************************************************************************** 708d05e84e6SDmitry Torokhov * Generic Part 709d05e84e6SDmitry Torokhov */ 710d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 711d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 712d05e84e6SDmitry Torokhov { 713d05e84e6SDmitry Torokhov struct usbtouch_device_info *type = usbtouch->type; 714d05e84e6SDmitry Torokhov 715d05e84e6SDmitry Torokhov if (!type->read_data(usbtouch, pkt)) 716d05e84e6SDmitry Torokhov return; 717d05e84e6SDmitry Torokhov 718d05e84e6SDmitry Torokhov input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 719d05e84e6SDmitry Torokhov 720d05e84e6SDmitry Torokhov if (swap_xy) { 721d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 722d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 723d05e84e6SDmitry Torokhov } else { 724d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 725d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 726d05e84e6SDmitry Torokhov } 727d05e84e6SDmitry Torokhov if (type->max_press) 728d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 729d05e84e6SDmitry Torokhov input_sync(usbtouch->input); 730d05e84e6SDmitry Torokhov } 731d05e84e6SDmitry Torokhov 732d05e84e6SDmitry Torokhov 733d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET 734d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 735d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 736d05e84e6SDmitry Torokhov { 737d05e84e6SDmitry Torokhov unsigned char *buffer; 738d05e84e6SDmitry Torokhov int pkt_len, pos, buf_len, tmp; 739d05e84e6SDmitry Torokhov 740d05e84e6SDmitry Torokhov /* process buffer */ 741d05e84e6SDmitry Torokhov if (unlikely(usbtouch->buf_len)) { 742d05e84e6SDmitry Torokhov /* try to get size */ 743d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 744d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 745d05e84e6SDmitry Torokhov 746d05e84e6SDmitry Torokhov /* drop? */ 747d05e84e6SDmitry Torokhov if (unlikely(!pkt_len)) 748d05e84e6SDmitry Torokhov goto out_flush_buf; 749d05e84e6SDmitry Torokhov 750d05e84e6SDmitry Torokhov /* need to append -pkt_len bytes before able to get size */ 751d05e84e6SDmitry Torokhov if (unlikely(pkt_len < 0)) { 752d05e84e6SDmitry Torokhov int append = -pkt_len; 753d05e84e6SDmitry Torokhov if (unlikely(append > len)) 754d05e84e6SDmitry Torokhov append = len; 755d05e84e6SDmitry Torokhov if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 756d05e84e6SDmitry Torokhov goto out_flush_buf; 757d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 758d05e84e6SDmitry Torokhov usbtouch->buf_len += append; 759d05e84e6SDmitry Torokhov 760d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 761d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 762d05e84e6SDmitry Torokhov if (pkt_len < 0) 763d05e84e6SDmitry Torokhov return; 764d05e84e6SDmitry Torokhov } 765d05e84e6SDmitry Torokhov 766d05e84e6SDmitry Torokhov /* append */ 767d05e84e6SDmitry Torokhov tmp = pkt_len - usbtouch->buf_len; 768d05e84e6SDmitry Torokhov if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 769d05e84e6SDmitry Torokhov goto out_flush_buf; 770d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 771d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 772d05e84e6SDmitry Torokhov 773d05e84e6SDmitry Torokhov buffer = pkt + tmp; 774d05e84e6SDmitry Torokhov buf_len = len - tmp; 775d05e84e6SDmitry Torokhov } else { 776d05e84e6SDmitry Torokhov buffer = pkt; 777d05e84e6SDmitry Torokhov buf_len = len; 778d05e84e6SDmitry Torokhov } 779d05e84e6SDmitry Torokhov 780d05e84e6SDmitry Torokhov /* loop over the received packet, process */ 781d05e84e6SDmitry Torokhov pos = 0; 782d05e84e6SDmitry Torokhov while (pos < buf_len) { 783d05e84e6SDmitry Torokhov /* get packet len */ 78462aa366dSDaniel Ritz pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 78562aa366dSDaniel Ritz buf_len - pos); 786d05e84e6SDmitry Torokhov 78762aa366dSDaniel Ritz /* unknown packet: skip one byte */ 78862aa366dSDaniel Ritz if (unlikely(!pkt_len)) { 78962aa366dSDaniel Ritz pos++; 79062aa366dSDaniel Ritz continue; 79162aa366dSDaniel Ritz } 792d05e84e6SDmitry Torokhov 793d05e84e6SDmitry Torokhov /* full packet: process */ 794d05e84e6SDmitry Torokhov if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 795d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 796d05e84e6SDmitry Torokhov } else { 797d05e84e6SDmitry Torokhov /* incomplete packet: save in buffer */ 798d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 799d05e84e6SDmitry Torokhov usbtouch->buf_len = buf_len - pos; 800d05e84e6SDmitry Torokhov return; 801d05e84e6SDmitry Torokhov } 802d05e84e6SDmitry Torokhov pos += pkt_len; 803d05e84e6SDmitry Torokhov } 804d05e84e6SDmitry Torokhov 805d05e84e6SDmitry Torokhov out_flush_buf: 806d05e84e6SDmitry Torokhov usbtouch->buf_len = 0; 807d05e84e6SDmitry Torokhov return; 808d05e84e6SDmitry Torokhov } 809d05e84e6SDmitry Torokhov #endif 810d05e84e6SDmitry Torokhov 811d05e84e6SDmitry Torokhov 812d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb) 813d05e84e6SDmitry Torokhov { 814d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = urb->context; 815d05e84e6SDmitry Torokhov int retval; 816d05e84e6SDmitry Torokhov 817d05e84e6SDmitry Torokhov switch (urb->status) { 818d05e84e6SDmitry Torokhov case 0: 819d05e84e6SDmitry Torokhov /* success */ 820d05e84e6SDmitry Torokhov break; 821d05e84e6SDmitry Torokhov case -ETIME: 822d05e84e6SDmitry Torokhov /* this urb is timing out */ 823d05e84e6SDmitry Torokhov dbg("%s - urb timed out - was the device unplugged?", 824ea3e6c59SHarvey Harrison __func__); 825d05e84e6SDmitry Torokhov return; 826d05e84e6SDmitry Torokhov case -ECONNRESET: 827d05e84e6SDmitry Torokhov case -ENOENT: 828d05e84e6SDmitry Torokhov case -ESHUTDOWN: 829d05e84e6SDmitry Torokhov /* this urb is terminated, clean up */ 830d05e84e6SDmitry Torokhov dbg("%s - urb shutting down with status: %d", 831ea3e6c59SHarvey Harrison __func__, urb->status); 832d05e84e6SDmitry Torokhov return; 833d05e84e6SDmitry Torokhov default: 834d05e84e6SDmitry Torokhov dbg("%s - nonzero urb status received: %d", 835ea3e6c59SHarvey Harrison __func__, urb->status); 836d05e84e6SDmitry Torokhov goto exit; 837d05e84e6SDmitry Torokhov } 838d05e84e6SDmitry Torokhov 839d05e84e6SDmitry Torokhov usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 840d05e84e6SDmitry Torokhov 841d05e84e6SDmitry Torokhov exit: 842d05e84e6SDmitry Torokhov retval = usb_submit_urb(urb, GFP_ATOMIC); 843d05e84e6SDmitry Torokhov if (retval) 844d05e84e6SDmitry Torokhov err("%s - usb_submit_urb failed with result: %d", 845ea3e6c59SHarvey Harrison __func__, retval); 846d05e84e6SDmitry Torokhov } 847d05e84e6SDmitry Torokhov 848d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input) 849d05e84e6SDmitry Torokhov { 850d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 851d05e84e6SDmitry Torokhov 852d05e84e6SDmitry Torokhov usbtouch->irq->dev = usbtouch->udev; 853d05e84e6SDmitry Torokhov 854d05e84e6SDmitry Torokhov if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) 855d05e84e6SDmitry Torokhov return -EIO; 856d05e84e6SDmitry Torokhov 857d05e84e6SDmitry Torokhov return 0; 858d05e84e6SDmitry Torokhov } 859d05e84e6SDmitry Torokhov 860d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input) 861d05e84e6SDmitry Torokhov { 862d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 863d05e84e6SDmitry Torokhov 864d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 865d05e84e6SDmitry Torokhov } 866d05e84e6SDmitry Torokhov 867d05e84e6SDmitry Torokhov 868d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev, 869d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch) 870d05e84e6SDmitry Torokhov { 871d05e84e6SDmitry Torokhov usb_buffer_free(udev, usbtouch->type->rept_size, 872d05e84e6SDmitry Torokhov usbtouch->data, usbtouch->data_dma); 873d05e84e6SDmitry Torokhov kfree(usbtouch->buffer); 874d05e84e6SDmitry Torokhov } 875d05e84e6SDmitry Torokhov 876d05e84e6SDmitry Torokhov 877d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf, 878d05e84e6SDmitry Torokhov const struct usb_device_id *id) 879d05e84e6SDmitry Torokhov { 880d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch; 881d05e84e6SDmitry Torokhov struct input_dev *input_dev; 882d05e84e6SDmitry Torokhov struct usb_host_interface *interface; 883d05e84e6SDmitry Torokhov struct usb_endpoint_descriptor *endpoint; 884d05e84e6SDmitry Torokhov struct usb_device *udev = interface_to_usbdev(intf); 885d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 886d05e84e6SDmitry Torokhov int err = -ENOMEM; 887d05e84e6SDmitry Torokhov 888ec42d448SDaniel Ritz /* some devices are ignored */ 889ec42d448SDaniel Ritz if (id->driver_info == DEVTYPE_IGNORE) 890ec42d448SDaniel Ritz return -ENODEV; 891ec42d448SDaniel Ritz 892d05e84e6SDmitry Torokhov interface = intf->cur_altsetting; 893d05e84e6SDmitry Torokhov endpoint = &interface->endpoint[0].desc; 894d05e84e6SDmitry Torokhov 895d05e84e6SDmitry Torokhov usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 896d05e84e6SDmitry Torokhov input_dev = input_allocate_device(); 897d05e84e6SDmitry Torokhov if (!usbtouch || !input_dev) 898d05e84e6SDmitry Torokhov goto out_free; 899d05e84e6SDmitry Torokhov 900d05e84e6SDmitry Torokhov type = &usbtouch_dev_info[id->driver_info]; 901d05e84e6SDmitry Torokhov usbtouch->type = type; 902d05e84e6SDmitry Torokhov if (!type->process_pkt) 903d05e84e6SDmitry Torokhov type->process_pkt = usbtouch_process_pkt; 904d05e84e6SDmitry Torokhov 905d05e84e6SDmitry Torokhov usbtouch->data = usb_buffer_alloc(udev, type->rept_size, 906d05e84e6SDmitry Torokhov GFP_KERNEL, &usbtouch->data_dma); 907d05e84e6SDmitry Torokhov if (!usbtouch->data) 908d05e84e6SDmitry Torokhov goto out_free; 909d05e84e6SDmitry Torokhov 91062aa366dSDaniel Ritz if (type->get_pkt_len) { 911d05e84e6SDmitry Torokhov usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 912d05e84e6SDmitry Torokhov if (!usbtouch->buffer) 913d05e84e6SDmitry Torokhov goto out_free_buffers; 914d05e84e6SDmitry Torokhov } 915d05e84e6SDmitry Torokhov 916d05e84e6SDmitry Torokhov usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 917d05e84e6SDmitry Torokhov if (!usbtouch->irq) { 918ea3e6c59SHarvey Harrison dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); 919d05e84e6SDmitry Torokhov goto out_free_buffers; 920d05e84e6SDmitry Torokhov } 921d05e84e6SDmitry Torokhov 922d05e84e6SDmitry Torokhov usbtouch->udev = udev; 923d05e84e6SDmitry Torokhov usbtouch->input = input_dev; 924d05e84e6SDmitry Torokhov 925d05e84e6SDmitry Torokhov if (udev->manufacturer) 926d05e84e6SDmitry Torokhov strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 927d05e84e6SDmitry Torokhov 928d05e84e6SDmitry Torokhov if (udev->product) { 929d05e84e6SDmitry Torokhov if (udev->manufacturer) 930d05e84e6SDmitry Torokhov strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 931d05e84e6SDmitry Torokhov strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 932d05e84e6SDmitry Torokhov } 933d05e84e6SDmitry Torokhov 934d05e84e6SDmitry Torokhov if (!strlen(usbtouch->name)) 935d05e84e6SDmitry Torokhov snprintf(usbtouch->name, sizeof(usbtouch->name), 936d05e84e6SDmitry Torokhov "USB Touchscreen %04x:%04x", 937d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idVendor), 938d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idProduct)); 939d05e84e6SDmitry Torokhov 940d05e84e6SDmitry Torokhov usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 9417b6dff98SVladimir Shebordaev strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 942d05e84e6SDmitry Torokhov 943d05e84e6SDmitry Torokhov input_dev->name = usbtouch->name; 944d05e84e6SDmitry Torokhov input_dev->phys = usbtouch->phys; 945d05e84e6SDmitry Torokhov usb_to_input_id(udev, &input_dev->id); 946d05e84e6SDmitry Torokhov input_dev->dev.parent = &intf->dev; 947d05e84e6SDmitry Torokhov 948d05e84e6SDmitry Torokhov input_set_drvdata(input_dev, usbtouch); 949d05e84e6SDmitry Torokhov 950d05e84e6SDmitry Torokhov input_dev->open = usbtouch_open; 951d05e84e6SDmitry Torokhov input_dev->close = usbtouch_close; 952d05e84e6SDmitry Torokhov 9537b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 9547b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 955d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 956d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 957d05e84e6SDmitry Torokhov if (type->max_press) 958d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 959d05e84e6SDmitry Torokhov type->max_press, 0, 0); 960d05e84e6SDmitry Torokhov 961d05e84e6SDmitry Torokhov usb_fill_int_urb(usbtouch->irq, usbtouch->udev, 962d05e84e6SDmitry Torokhov usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), 963d05e84e6SDmitry Torokhov usbtouch->data, type->rept_size, 964d05e84e6SDmitry Torokhov usbtouch_irq, usbtouch, endpoint->bInterval); 965d05e84e6SDmitry Torokhov 966d05e84e6SDmitry Torokhov usbtouch->irq->dev = usbtouch->udev; 967d05e84e6SDmitry Torokhov usbtouch->irq->transfer_dma = usbtouch->data_dma; 968d05e84e6SDmitry Torokhov usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 969d05e84e6SDmitry Torokhov 970d05e84e6SDmitry Torokhov /* device specific init */ 971d05e84e6SDmitry Torokhov if (type->init) { 972d05e84e6SDmitry Torokhov err = type->init(usbtouch); 973d05e84e6SDmitry Torokhov if (err) { 974ea3e6c59SHarvey Harrison dbg("%s - type->init() failed, err: %d", __func__, err); 975d05e84e6SDmitry Torokhov goto out_free_buffers; 976d05e84e6SDmitry Torokhov } 977d05e84e6SDmitry Torokhov } 978d05e84e6SDmitry Torokhov 979d05e84e6SDmitry Torokhov err = input_register_device(usbtouch->input); 980d05e84e6SDmitry Torokhov if (err) { 981ea3e6c59SHarvey Harrison dbg("%s - input_register_device failed, err: %d", __func__, err); 982d05e84e6SDmitry Torokhov goto out_free_buffers; 983d05e84e6SDmitry Torokhov } 984d05e84e6SDmitry Torokhov 985d05e84e6SDmitry Torokhov usb_set_intfdata(intf, usbtouch); 986d05e84e6SDmitry Torokhov 987d05e84e6SDmitry Torokhov return 0; 988d05e84e6SDmitry Torokhov 989d05e84e6SDmitry Torokhov out_free_buffers: 990d05e84e6SDmitry Torokhov usbtouch_free_buffers(udev, usbtouch); 991d05e84e6SDmitry Torokhov out_free: 992d05e84e6SDmitry Torokhov input_free_device(input_dev); 993d05e84e6SDmitry Torokhov kfree(usbtouch); 994d05e84e6SDmitry Torokhov return err; 995d05e84e6SDmitry Torokhov } 996d05e84e6SDmitry Torokhov 997d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf) 998d05e84e6SDmitry Torokhov { 999d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1000d05e84e6SDmitry Torokhov 1001ea3e6c59SHarvey Harrison dbg("%s - called", __func__); 1002d05e84e6SDmitry Torokhov 1003d05e84e6SDmitry Torokhov if (!usbtouch) 1004d05e84e6SDmitry Torokhov return; 1005d05e84e6SDmitry Torokhov 1006ea3e6c59SHarvey Harrison dbg("%s - usbtouch is initialized, cleaning up", __func__); 1007d05e84e6SDmitry Torokhov usb_set_intfdata(intf, NULL); 1008d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 1009d05e84e6SDmitry Torokhov input_unregister_device(usbtouch->input); 1010d05e84e6SDmitry Torokhov usb_free_urb(usbtouch->irq); 1011d05e84e6SDmitry Torokhov usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 1012d05e84e6SDmitry Torokhov kfree(usbtouch); 1013d05e84e6SDmitry Torokhov } 1014d05e84e6SDmitry Torokhov 1015d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices); 1016d05e84e6SDmitry Torokhov 1017d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = { 1018d05e84e6SDmitry Torokhov .name = "usbtouchscreen", 1019d05e84e6SDmitry Torokhov .probe = usbtouch_probe, 1020d05e84e6SDmitry Torokhov .disconnect = usbtouch_disconnect, 1021d05e84e6SDmitry Torokhov .id_table = usbtouch_devices, 1022d05e84e6SDmitry Torokhov }; 1023d05e84e6SDmitry Torokhov 1024d05e84e6SDmitry Torokhov static int __init usbtouch_init(void) 1025d05e84e6SDmitry Torokhov { 1026d05e84e6SDmitry Torokhov return usb_register(&usbtouch_driver); 1027d05e84e6SDmitry Torokhov } 1028d05e84e6SDmitry Torokhov 1029d05e84e6SDmitry Torokhov static void __exit usbtouch_cleanup(void) 1030d05e84e6SDmitry Torokhov { 1031d05e84e6SDmitry Torokhov usb_deregister(&usbtouch_driver); 1032d05e84e6SDmitry Torokhov } 1033d05e84e6SDmitry Torokhov 1034d05e84e6SDmitry Torokhov module_init(usbtouch_init); 1035d05e84e6SDmitry Torokhov module_exit(usbtouch_cleanup); 1036d05e84e6SDmitry Torokhov 1037d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR); 1038d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC); 1039d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL"); 1040d05e84e6SDmitry Torokhov 1041d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb"); 1042d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch"); 1043d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb"); 1044