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 16f7370699SJim Persson * - JASTEC USB touch controller/DigiTech DTR-02U 172330ed18SDaniel Silverstone * - Zytronic capacitive touchscreen 185197424cSOndrej Zary * - NEXIO/iNexio 19d2cc817aSMichael Gebetsroither * - Elo TouchSystems 2700 IntelliTouch 20aa87512fSArmando Visconti * - EasyTouch USB Dual/Multi touch controller from Data Modul 21d05e84e6SDmitry Torokhov * 2214e40206SJerrold Jones * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 23d05e84e6SDmitry Torokhov * Copyright (C) by Todd E. Johnson (mtouchusb.c) 24d05e84e6SDmitry Torokhov * 25d05e84e6SDmitry Torokhov * This program is free software; you can redistribute it and/or 26d05e84e6SDmitry Torokhov * modify it under the terms of the GNU General Public License as 27d05e84e6SDmitry Torokhov * published by the Free Software Foundation; either version 2 of the 28d05e84e6SDmitry Torokhov * License, or (at your option) any later version. 29d05e84e6SDmitry Torokhov * 30d05e84e6SDmitry Torokhov * This program is distributed in the hope that it will be useful, but 31d05e84e6SDmitry Torokhov * WITHOUT ANY WARRANTY; without even the implied warranty of 32d05e84e6SDmitry Torokhov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33d05e84e6SDmitry Torokhov * General Public License for more details. 34d05e84e6SDmitry Torokhov * 35d05e84e6SDmitry Torokhov * You should have received a copy of the GNU General Public License 36d05e84e6SDmitry Torokhov * along with this program; if not, write to the Free Software 37d05e84e6SDmitry Torokhov * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 38d05e84e6SDmitry Torokhov * 39d05e84e6SDmitry Torokhov * Driver is based on touchkitusb.c 40d05e84e6SDmitry Torokhov * - ITM parts are from itmtouch.c 41d05e84e6SDmitry Torokhov * - 3M parts are from mtouchusb.c 42d05e84e6SDmitry Torokhov * - PanJit parts are from an unmerged driver by Lanslott Gish 43d05e84e6SDmitry Torokhov * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged 44d05e84e6SDmitry Torokhov * driver from Marius Vollmer 45d05e84e6SDmitry Torokhov * 46d05e84e6SDmitry Torokhov *****************************************************************************/ 47d05e84e6SDmitry Torokhov 48d05e84e6SDmitry Torokhov //#define DEBUG 49d05e84e6SDmitry Torokhov 50d05e84e6SDmitry Torokhov #include <linux/kernel.h> 51d05e84e6SDmitry Torokhov #include <linux/slab.h> 52d05e84e6SDmitry Torokhov #include <linux/input.h> 53d05e84e6SDmitry Torokhov #include <linux/module.h> 54d05e84e6SDmitry Torokhov #include <linux/init.h> 55d05e84e6SDmitry Torokhov #include <linux/usb.h> 56d05e84e6SDmitry Torokhov #include <linux/usb/input.h> 57ec42d448SDaniel Ritz #include <linux/hid.h> 58d05e84e6SDmitry Torokhov 59d05e84e6SDmitry Torokhov 6062aa366dSDaniel Ritz #define DRIVER_VERSION "v0.6" 61d05e84e6SDmitry Torokhov #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 62d05e84e6SDmitry Torokhov #define DRIVER_DESC "USB Touchscreen Driver" 63d05e84e6SDmitry Torokhov 6490ab5ee9SRusty Russell static bool swap_xy; 65d05e84e6SDmitry Torokhov module_param(swap_xy, bool, 0644); 66d05e84e6SDmitry Torokhov MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 67d05e84e6SDmitry Torokhov 6890ab5ee9SRusty Russell static bool hwcalib_xy; 69c9cbf3d3SDan Streetman module_param(hwcalib_xy, bool, 0644); 70c9cbf3d3SDan Streetman MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); 71c9cbf3d3SDan Streetman 72d05e84e6SDmitry Torokhov /* device specifc data/functions */ 73d05e84e6SDmitry Torokhov struct usbtouch_usb; 74d05e84e6SDmitry Torokhov struct usbtouch_device_info { 75d05e84e6SDmitry Torokhov int min_xc, max_xc; 76d05e84e6SDmitry Torokhov int min_yc, max_yc; 77d05e84e6SDmitry Torokhov int min_press, max_press; 78d05e84e6SDmitry Torokhov int rept_size; 79d05e84e6SDmitry Torokhov 802330ed18SDaniel Silverstone /* 812330ed18SDaniel Silverstone * Always service the USB devices irq not just when the input device is 822330ed18SDaniel Silverstone * open. This is useful when devices have a watchdog which prevents us 832330ed18SDaniel Silverstone * from periodically polling the device. Leave this unset unless your 842330ed18SDaniel Silverstone * touchscreen device requires it, as it does consume more of the USB 852330ed18SDaniel Silverstone * bandwidth. 862330ed18SDaniel Silverstone */ 872330ed18SDaniel Silverstone bool irq_always; 882330ed18SDaniel Silverstone 89d05e84e6SDmitry Torokhov void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); 9062aa366dSDaniel Ritz 9162aa366dSDaniel Ritz /* 9262aa366dSDaniel Ritz * used to get the packet len. possible return values: 9362aa366dSDaniel Ritz * > 0: packet len 9462aa366dSDaniel Ritz * = 0: skip one byte 9562aa366dSDaniel Ritz * < 0: -return value more bytes needed 9662aa366dSDaniel Ritz */ 97d05e84e6SDmitry Torokhov int (*get_pkt_len) (unsigned char *pkt, int len); 9862aa366dSDaniel Ritz 99d05e84e6SDmitry Torokhov int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); 100a8aef622SOliver Neukum int (*alloc) (struct usbtouch_usb *usbtouch); 101d05e84e6SDmitry Torokhov int (*init) (struct usbtouch_usb *usbtouch); 1025197424cSOndrej Zary void (*exit) (struct usbtouch_usb *usbtouch); 103d05e84e6SDmitry Torokhov }; 104d05e84e6SDmitry Torokhov 105d05e84e6SDmitry Torokhov /* a usbtouch device */ 106d05e84e6SDmitry Torokhov struct usbtouch_usb { 107d05e84e6SDmitry Torokhov unsigned char *data; 108d05e84e6SDmitry Torokhov dma_addr_t data_dma; 109d05e84e6SDmitry Torokhov unsigned char *buffer; 110d05e84e6SDmitry Torokhov int buf_len; 111d05e84e6SDmitry Torokhov struct urb *irq; 112fea4d14bSOndrej Zary struct usb_interface *interface; 113d05e84e6SDmitry Torokhov struct input_dev *input; 114d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 115d05e84e6SDmitry Torokhov char name[128]; 116d05e84e6SDmitry Torokhov char phys[64]; 1175197424cSOndrej Zary void *priv; 118d05e84e6SDmitry Torokhov 119d05e84e6SDmitry Torokhov int x, y; 120d05e84e6SDmitry Torokhov int touch, press; 121d05e84e6SDmitry Torokhov }; 122d05e84e6SDmitry Torokhov 123d05e84e6SDmitry Torokhov 124d05e84e6SDmitry Torokhov /* device types */ 125d05e84e6SDmitry Torokhov enum { 126ec42d448SDaniel Ritz DEVTYPE_IGNORE = -1, 127d05e84e6SDmitry Torokhov DEVTYPE_EGALAX, 128d05e84e6SDmitry Torokhov DEVTYPE_PANJIT, 129d05e84e6SDmitry Torokhov DEVTYPE_3M, 130d05e84e6SDmitry Torokhov DEVTYPE_ITM, 131d05e84e6SDmitry Torokhov DEVTYPE_ETURBO, 132d05e84e6SDmitry Torokhov DEVTYPE_GUNZE, 133d05e84e6SDmitry Torokhov DEVTYPE_DMC_TSC10, 134df561fcdSOndrej Zary DEVTYPE_IRTOUCH, 135a14a8401SOndrej Zary DEVTYPE_IDEALTEK, 1369d5657dbSIlya Frolov DEVTYPE_GENERAL_TOUCH, 13714e40206SJerrold Jones DEVTYPE_GOTOP, 138f7370699SJim Persson DEVTYPE_JASTEC, 1399e3b2583SFlorian Echtler DEVTYPE_E2I, 1402330ed18SDaniel Silverstone DEVTYPE_ZYTRONIC, 14138771bb4SPetr Štetiar DEVTYPE_TC45USB, 1425197424cSOndrej Zary DEVTYPE_NEXIO, 143d2cc817aSMichael Gebetsroither DEVTYPE_ELO, 144aa87512fSArmando Visconti DEVTYPE_ETOUCH, 145d05e84e6SDmitry Torokhov }; 146d05e84e6SDmitry Torokhov 147ec42d448SDaniel Ritz #define USB_DEVICE_HID_CLASS(vend, prod) \ 148ec42d448SDaniel Ritz .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ 149ec42d448SDaniel Ritz | USB_DEVICE_ID_MATCH_DEVICE, \ 150ec42d448SDaniel Ritz .idVendor = (vend), \ 151ec42d448SDaniel Ritz .idProduct = (prod), \ 152*ae2aa3a5SForest Bond .bInterfaceClass = USB_INTERFACE_CLASS_HID 153ec42d448SDaniel Ritz 1549cb3ce52SMárton Németh static const struct usb_device_id usbtouch_devices[] = { 155c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 156ec42d448SDaniel Ritz /* ignore the HID capable devices, handled by usbhid */ 157ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 158ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 159ec42d448SDaniel Ritz 160ec42d448SDaniel Ritz /* normal device IDs */ 161d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 162d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 163d05e84e6SDmitry Torokhov {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 164d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 165d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 166d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 167d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 168d05e84e6SDmitry Torokhov #endif 169d05e84e6SDmitry Torokhov 170c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 171d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 172d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 173d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 174d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 175d05e84e6SDmitry Torokhov #endif 176d05e84e6SDmitry Torokhov 177c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 178d05e84e6SDmitry Torokhov {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 179d05e84e6SDmitry Torokhov #endif 180d05e84e6SDmitry Torokhov 181c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 182d05e84e6SDmitry Torokhov {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 18309910509SGlenn Sommer {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, 184d05e84e6SDmitry Torokhov #endif 185d05e84e6SDmitry Torokhov 186c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 187d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 188d05e84e6SDmitry Torokhov #endif 189d05e84e6SDmitry Torokhov 190c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 191d05e84e6SDmitry Torokhov {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 192d05e84e6SDmitry Torokhov #endif 193d05e84e6SDmitry Torokhov 194c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 195d05e84e6SDmitry Torokhov {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 196d05e84e6SDmitry Torokhov #endif 197d05e84e6SDmitry Torokhov 198df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 199df561fcdSOndrej Zary {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 200df561fcdSOndrej Zary {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 201df561fcdSOndrej Zary #endif 202df561fcdSOndrej Zary 203a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 204a14a8401SOndrej Zary {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 205a14a8401SOndrej Zary #endif 206a14a8401SOndrej Zary 2079d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 2089d5657dbSIlya Frolov {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 2099d5657dbSIlya Frolov #endif 2109d5657dbSIlya Frolov 21114e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 21214e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 21314e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 21414e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 21514e40206SJerrold Jones #endif 21614e40206SJerrold Jones 217f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 218f7370699SJim Persson {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, 219f7370699SJim Persson #endif 220f7370699SJim Persson 2219e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2229e3b2583SFlorian Echtler {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, 2239e3b2583SFlorian Echtler #endif 2242330ed18SDaniel Silverstone 2252330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 2262330ed18SDaniel Silverstone {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, 2272330ed18SDaniel Silverstone #endif 2282330ed18SDaniel Silverstone 22938771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 23038771bb4SPetr Štetiar /* TC5UH */ 23138771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, 23238771bb4SPetr Štetiar /* TC4UM */ 23338771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, 234dbe1420bSPetr Štetiar #endif 235dbe1420bSPetr Štetiar 2365197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 2375197424cSOndrej Zary /* data interface only */ 2385197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), 2395197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2405197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), 2415197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2425197424cSOndrej Zary #endif 2435197424cSOndrej Zary 244d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 245d2cc817aSMichael Gebetsroither {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, 246d2cc817aSMichael Gebetsroither #endif 247d2cc817aSMichael Gebetsroither 248aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 249aa87512fSArmando Visconti {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, 250aa87512fSArmando Visconti #endif 251aa87512fSArmando Visconti 252d05e84e6SDmitry Torokhov {} 253d05e84e6SDmitry Torokhov }; 254d05e84e6SDmitry Torokhov 255d05e84e6SDmitry Torokhov 256d05e84e6SDmitry Torokhov /***************************************************************************** 2579e3b2583SFlorian Echtler * e2i Part 2589e3b2583SFlorian Echtler */ 2599e3b2583SFlorian Echtler 2609e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2619e3b2583SFlorian Echtler static int e2i_init(struct usbtouch_usb *usbtouch) 2629e3b2583SFlorian Echtler { 2639e3b2583SFlorian Echtler int ret; 264fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 2659e3b2583SFlorian Echtler 266fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 2679e3b2583SFlorian Echtler 0x01, 0x02, 0x0000, 0x0081, 2689e3b2583SFlorian Echtler NULL, 0, USB_CTRL_SET_TIMEOUT); 2699e3b2583SFlorian Echtler 2700a5ebc88SGreg Kroah-Hartman dev_dbg(&usbtouch->interface->dev, 271b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n", 2729e3b2583SFlorian Echtler __func__, ret); 2739e3b2583SFlorian Echtler return ret; 2749e3b2583SFlorian Echtler } 2759e3b2583SFlorian Echtler 2769e3b2583SFlorian Echtler static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 2779e3b2583SFlorian Echtler { 2789e3b2583SFlorian Echtler int tmp = (pkt[0] << 8) | pkt[1]; 2799e3b2583SFlorian Echtler dev->x = (pkt[2] << 8) | pkt[3]; 2809e3b2583SFlorian Echtler dev->y = (pkt[4] << 8) | pkt[5]; 2819e3b2583SFlorian Echtler 2829e3b2583SFlorian Echtler tmp = tmp - 0xA000; 2839e3b2583SFlorian Echtler dev->touch = (tmp > 0); 2849e3b2583SFlorian Echtler dev->press = (tmp > 0 ? tmp : 0); 2859e3b2583SFlorian Echtler 2869e3b2583SFlorian Echtler return 1; 2879e3b2583SFlorian Echtler } 2889e3b2583SFlorian Echtler #endif 2899e3b2583SFlorian Echtler 2909e3b2583SFlorian Echtler 2919e3b2583SFlorian Echtler /***************************************************************************** 292d05e84e6SDmitry Torokhov * eGalax part 293d05e84e6SDmitry Torokhov */ 294d05e84e6SDmitry Torokhov 295c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 296d05e84e6SDmitry Torokhov 29762aa366dSDaniel Ritz #ifndef MULTI_PACKET 29862aa366dSDaniel Ritz #define MULTI_PACKET 29962aa366dSDaniel Ritz #endif 30062aa366dSDaniel Ritz 301d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK 0xFE 302d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT 0x80 303d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG 0x0A 304d05e84e6SDmitry Torokhov 305037a833eSForest Bond static int egalax_init(struct usbtouch_usb *usbtouch) 306037a833eSForest Bond { 307037a833eSForest Bond int ret, i; 308037a833eSForest Bond unsigned char *buf; 309037a833eSForest Bond struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 310037a833eSForest Bond 311037a833eSForest Bond /* 312037a833eSForest Bond * An eGalax diagnostic packet kicks the device into using the right 313037a833eSForest Bond * protocol. We send a "check active" packet. The response will be 314037a833eSForest Bond * read later and ignored. 315037a833eSForest Bond */ 316037a833eSForest Bond 317037a833eSForest Bond buf = kmalloc(3, GFP_KERNEL); 318037a833eSForest Bond if (!buf) 319037a833eSForest Bond return -ENOMEM; 320037a833eSForest Bond 321037a833eSForest Bond buf[0] = EGALAX_PKT_TYPE_DIAG; 322037a833eSForest Bond buf[1] = 1; /* length */ 323037a833eSForest Bond buf[2] = 'A'; /* command - check active */ 324037a833eSForest Bond 325037a833eSForest Bond for (i = 0; i < 3; i++) { 326037a833eSForest Bond ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 327037a833eSForest Bond 0, 328037a833eSForest Bond USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 329037a833eSForest Bond 0, 0, buf, 3, 330037a833eSForest Bond USB_CTRL_SET_TIMEOUT); 331037a833eSForest Bond if (ret >= 0) { 332037a833eSForest Bond ret = 0; 333037a833eSForest Bond break; 334037a833eSForest Bond } 335037a833eSForest Bond if (ret != -EPIPE) 336037a833eSForest Bond break; 337037a833eSForest Bond } 338037a833eSForest Bond 339037a833eSForest Bond kfree(buf); 340037a833eSForest Bond 341037a833eSForest Bond return ret; 342037a833eSForest Bond } 343037a833eSForest Bond 344d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 345d05e84e6SDmitry Torokhov { 346d05e84e6SDmitry Torokhov if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 347d05e84e6SDmitry Torokhov return 0; 348d05e84e6SDmitry Torokhov 349d05e84e6SDmitry Torokhov dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 350d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 351d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 352d05e84e6SDmitry Torokhov 353d05e84e6SDmitry Torokhov return 1; 354d05e84e6SDmitry Torokhov } 355d05e84e6SDmitry Torokhov 356d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len) 357d05e84e6SDmitry Torokhov { 358d05e84e6SDmitry Torokhov switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 359d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_REPT: 360d05e84e6SDmitry Torokhov return 5; 361d05e84e6SDmitry Torokhov 362d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_DIAG: 363d05e84e6SDmitry Torokhov if (len < 2) 364d05e84e6SDmitry Torokhov return -1; 365d05e84e6SDmitry Torokhov 366d05e84e6SDmitry Torokhov return buf[1] + 2; 367d05e84e6SDmitry Torokhov } 368d05e84e6SDmitry Torokhov 369d05e84e6SDmitry Torokhov return 0; 370d05e84e6SDmitry Torokhov } 371d05e84e6SDmitry Torokhov #endif 372d05e84e6SDmitry Torokhov 373aa87512fSArmando Visconti /***************************************************************************** 374aa87512fSArmando Visconti * EasyTouch part 375aa87512fSArmando Visconti */ 376aa87512fSArmando Visconti 377aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 378aa87512fSArmando Visconti 379aa87512fSArmando Visconti #ifndef MULTI_PACKET 380aa87512fSArmando Visconti #define MULTI_PACKET 381aa87512fSArmando Visconti #endif 382aa87512fSArmando Visconti 383aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_MASK 0xFE 384aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT 0x80 385aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT2 0xB0 386aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_DIAG 0x0A 387aa87512fSArmando Visconti 388aa87512fSArmando Visconti static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 389aa87512fSArmando Visconti { 390aa87512fSArmando Visconti if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && 391aa87512fSArmando Visconti (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) 392aa87512fSArmando Visconti return 0; 393aa87512fSArmando Visconti 394aa87512fSArmando Visconti dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); 395aa87512fSArmando Visconti dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); 396aa87512fSArmando Visconti dev->touch = pkt[0] & 0x01; 397aa87512fSArmando Visconti 398aa87512fSArmando Visconti return 1; 399aa87512fSArmando Visconti } 400aa87512fSArmando Visconti 401aa87512fSArmando Visconti static int etouch_get_pkt_len(unsigned char *buf, int len) 402aa87512fSArmando Visconti { 403aa87512fSArmando Visconti switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { 404aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_REPT: 405aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_REPT2: 406aa87512fSArmando Visconti return 5; 407aa87512fSArmando Visconti 408aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_DIAG: 409aa87512fSArmando Visconti if (len < 2) 410aa87512fSArmando Visconti return -1; 411aa87512fSArmando Visconti 412aa87512fSArmando Visconti return buf[1] + 2; 413aa87512fSArmando Visconti } 414aa87512fSArmando Visconti 415aa87512fSArmando Visconti return 0; 416aa87512fSArmando Visconti } 417aa87512fSArmando Visconti #endif 418d05e84e6SDmitry Torokhov 419d05e84e6SDmitry Torokhov /***************************************************************************** 420d05e84e6SDmitry Torokhov * PanJit Part 421d05e84e6SDmitry Torokhov */ 422c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 423d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 424d05e84e6SDmitry Torokhov { 425d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 426d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 427d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 428d05e84e6SDmitry Torokhov 429d05e84e6SDmitry Torokhov return 1; 430d05e84e6SDmitry Torokhov } 431d05e84e6SDmitry Torokhov #endif 432d05e84e6SDmitry Torokhov 433d05e84e6SDmitry Torokhov 434d05e84e6SDmitry Torokhov /***************************************************************************** 435d05e84e6SDmitry Torokhov * 3M/Microtouch Part 436d05e84e6SDmitry Torokhov */ 437c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 438d05e84e6SDmitry Torokhov 439d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT 1 440d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET 7 441d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID 10 442d05e84e6SDmitry Torokhov 443d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 444d05e84e6SDmitry Torokhov { 445c9cbf3d3SDan Streetman if (hwcalib_xy) { 446c9cbf3d3SDan Streetman dev->x = (pkt[4] << 8) | pkt[3]; 447c9cbf3d3SDan Streetman dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 448c9cbf3d3SDan Streetman } else { 449d05e84e6SDmitry Torokhov dev->x = (pkt[8] << 8) | pkt[7]; 450d05e84e6SDmitry Torokhov dev->y = (pkt[10] << 8) | pkt[9]; 451c9cbf3d3SDan Streetman } 452d05e84e6SDmitry Torokhov dev->touch = (pkt[2] & 0x40) ? 1 : 0; 453d05e84e6SDmitry Torokhov 454d05e84e6SDmitry Torokhov return 1; 455d05e84e6SDmitry Torokhov } 456d05e84e6SDmitry Torokhov 457d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch) 458d05e84e6SDmitry Torokhov { 459d05e84e6SDmitry Torokhov int ret, i; 460fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 461d05e84e6SDmitry Torokhov 462fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 463d05e84e6SDmitry Torokhov MTOUCHUSB_RESET, 464d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 465d05e84e6SDmitry Torokhov 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 4660a5ebc88SGreg Kroah-Hartman dev_dbg(&usbtouch->interface->dev, 467b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n", 468ea3e6c59SHarvey Harrison __func__, ret); 469d05e84e6SDmitry Torokhov if (ret < 0) 470d05e84e6SDmitry Torokhov return ret; 471d05e84e6SDmitry Torokhov msleep(150); 472d05e84e6SDmitry Torokhov 473d05e84e6SDmitry Torokhov for (i = 0; i < 3; i++) { 474fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 475d05e84e6SDmitry Torokhov MTOUCHUSB_ASYNC_REPORT, 476d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 477d05e84e6SDmitry Torokhov 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 4780a5ebc88SGreg Kroah-Hartman dev_dbg(&usbtouch->interface->dev, 479b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n", 480ea3e6c59SHarvey Harrison __func__, ret); 481d05e84e6SDmitry Torokhov if (ret >= 0) 482d05e84e6SDmitry Torokhov break; 483d05e84e6SDmitry Torokhov if (ret != -EPIPE) 484d05e84e6SDmitry Torokhov return ret; 485d05e84e6SDmitry Torokhov } 486d05e84e6SDmitry Torokhov 487c9cbf3d3SDan Streetman /* Default min/max xy are the raw values, override if using hw-calib */ 488c9cbf3d3SDan Streetman if (hwcalib_xy) { 489c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 490c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 491c9cbf3d3SDan Streetman } 492c9cbf3d3SDan Streetman 493d05e84e6SDmitry Torokhov return 0; 494d05e84e6SDmitry Torokhov } 495d05e84e6SDmitry Torokhov #endif 496d05e84e6SDmitry Torokhov 497d05e84e6SDmitry Torokhov 498d05e84e6SDmitry Torokhov /***************************************************************************** 499d05e84e6SDmitry Torokhov * ITM Part 500d05e84e6SDmitry Torokhov */ 501c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 502d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 503d05e84e6SDmitry Torokhov { 504d05e84e6SDmitry Torokhov int touch; 505d05e84e6SDmitry Torokhov /* 506d05e84e6SDmitry Torokhov * ITM devices report invalid x/y data if not touched. 507d05e84e6SDmitry Torokhov * if the screen was touched before but is not touched any more 508d05e84e6SDmitry Torokhov * report touch as 0 with the last valid x/y data once. then stop 509d05e84e6SDmitry Torokhov * reporting data until touched again. 510d05e84e6SDmitry Torokhov */ 511d05e84e6SDmitry Torokhov dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 512d05e84e6SDmitry Torokhov 513d05e84e6SDmitry Torokhov touch = ~pkt[7] & 0x20; 514d05e84e6SDmitry Torokhov if (!touch) { 515d05e84e6SDmitry Torokhov if (dev->touch) { 516d05e84e6SDmitry Torokhov dev->touch = 0; 517d05e84e6SDmitry Torokhov return 1; 518d05e84e6SDmitry Torokhov } 519d05e84e6SDmitry Torokhov 520d05e84e6SDmitry Torokhov return 0; 521d05e84e6SDmitry Torokhov } 522d05e84e6SDmitry Torokhov 523d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 524d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 525d05e84e6SDmitry Torokhov dev->touch = touch; 526d05e84e6SDmitry Torokhov 527d05e84e6SDmitry Torokhov return 1; 528d05e84e6SDmitry Torokhov } 529d05e84e6SDmitry Torokhov #endif 530d05e84e6SDmitry Torokhov 531d05e84e6SDmitry Torokhov 532d05e84e6SDmitry Torokhov /***************************************************************************** 533d05e84e6SDmitry Torokhov * eTurboTouch part 534d05e84e6SDmitry Torokhov */ 535c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 53662aa366dSDaniel Ritz #ifndef MULTI_PACKET 53762aa366dSDaniel Ritz #define MULTI_PACKET 53862aa366dSDaniel Ritz #endif 539d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 540d05e84e6SDmitry Torokhov { 541d05e84e6SDmitry Torokhov unsigned int shift; 542d05e84e6SDmitry Torokhov 543d05e84e6SDmitry Torokhov /* packets should start with sync */ 544d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80)) 545d05e84e6SDmitry Torokhov return 0; 546d05e84e6SDmitry Torokhov 547d05e84e6SDmitry Torokhov shift = (6 - (pkt[0] & 0x03)); 548d05e84e6SDmitry Torokhov dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 549d05e84e6SDmitry Torokhov dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 550d05e84e6SDmitry Torokhov dev->touch = (pkt[0] & 0x10) ? 1 : 0; 551d05e84e6SDmitry Torokhov 552d05e84e6SDmitry Torokhov return 1; 553d05e84e6SDmitry Torokhov } 554d05e84e6SDmitry Torokhov 555d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len) 556d05e84e6SDmitry Torokhov { 557d05e84e6SDmitry Torokhov if (buf[0] & 0x80) 558d05e84e6SDmitry Torokhov return 5; 559d05e84e6SDmitry Torokhov if (buf[0] == 0x01) 560d05e84e6SDmitry Torokhov return 3; 561d05e84e6SDmitry Torokhov return 0; 562d05e84e6SDmitry Torokhov } 563d05e84e6SDmitry Torokhov #endif 564d05e84e6SDmitry Torokhov 565d05e84e6SDmitry Torokhov 566d05e84e6SDmitry Torokhov /***************************************************************************** 567d05e84e6SDmitry Torokhov * Gunze part 568d05e84e6SDmitry Torokhov */ 569c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 570d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 571d05e84e6SDmitry Torokhov { 572d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 573d05e84e6SDmitry Torokhov return 0; 574d05e84e6SDmitry Torokhov 575d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 576d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 577d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x20; 578d05e84e6SDmitry Torokhov 579d05e84e6SDmitry Torokhov return 1; 580d05e84e6SDmitry Torokhov } 581d05e84e6SDmitry Torokhov #endif 582d05e84e6SDmitry Torokhov 583d05e84e6SDmitry Torokhov /***************************************************************************** 584d05e84e6SDmitry Torokhov * DMC TSC-10/25 Part 585d05e84e6SDmitry Torokhov * 586d05e84e6SDmitry Torokhov * Documentation about the controller and it's protocol can be found at 587d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 588d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 589d05e84e6SDmitry Torokhov */ 590c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 591d05e84e6SDmitry Torokhov 592d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */ 593d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT 0x50 594d05e84e6SDmitry Torokhov #define TSC10_RATE_30 0x40 595d05e84e6SDmitry Torokhov #define TSC10_RATE_50 0x41 596d05e84e6SDmitry Torokhov #define TSC10_RATE_80 0x42 597d05e84e6SDmitry Torokhov #define TSC10_RATE_100 0x43 598d05e84e6SDmitry Torokhov #define TSC10_RATE_130 0x44 599d05e84e6SDmitry Torokhov #define TSC10_RATE_150 0x45 600d05e84e6SDmitry Torokhov 601d05e84e6SDmitry Torokhov /* commands */ 602d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET 0x55 603d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE 0x05 604d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1 0x01 605d05e84e6SDmitry Torokhov 606d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 607d05e84e6SDmitry Torokhov { 608fea4d14bSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 60976d057ceSOliver Neukum int ret = -ENOMEM; 61076d057ceSOliver Neukum unsigned char *buf; 611d05e84e6SDmitry Torokhov 612a8aef622SOliver Neukum buf = kmalloc(2, GFP_NOIO); 61376d057ceSOliver Neukum if (!buf) 61476d057ceSOliver Neukum goto err_nobuf; 615d05e84e6SDmitry Torokhov /* reset */ 616d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 617d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 618d05e84e6SDmitry Torokhov TSC10_CMD_RESET, 619d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 620d05e84e6SDmitry Torokhov 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 621d05e84e6SDmitry Torokhov if (ret < 0) 62276d057ceSOliver Neukum goto err_out; 6232ec6f246SNuno Lucas if (buf[0] != 0x06) { 62476d057ceSOliver Neukum ret = -ENODEV; 62576d057ceSOliver Neukum goto err_out; 62676d057ceSOliver Neukum } 627d05e84e6SDmitry Torokhov 628d05e84e6SDmitry Torokhov /* set coordinate output rate */ 629d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 630d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 631d05e84e6SDmitry Torokhov TSC10_CMD_RATE, 632d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 633d05e84e6SDmitry Torokhov TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 634d05e84e6SDmitry Torokhov if (ret < 0) 63576d057ceSOliver Neukum goto err_out; 6362ec6f246SNuno Lucas if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 63776d057ceSOliver Neukum ret = -ENODEV; 63876d057ceSOliver Neukum goto err_out; 63976d057ceSOliver Neukum } 640d05e84e6SDmitry Torokhov 641d05e84e6SDmitry Torokhov /* start sending data */ 642d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 643d05e84e6SDmitry Torokhov TSC10_CMD_DATA1, 644d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 645d05e84e6SDmitry Torokhov 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 64676d057ceSOliver Neukum err_out: 64776d057ceSOliver Neukum kfree(buf); 64876d057ceSOliver Neukum err_nobuf: 649d05e84e6SDmitry Torokhov return ret; 650d05e84e6SDmitry Torokhov } 651d05e84e6SDmitry Torokhov 652d05e84e6SDmitry Torokhov 653d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 654d05e84e6SDmitry Torokhov { 655d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 656d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 657d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 658d05e84e6SDmitry Torokhov 659d05e84e6SDmitry Torokhov return 1; 660d05e84e6SDmitry Torokhov } 661d05e84e6SDmitry Torokhov #endif 662d05e84e6SDmitry Torokhov 663d05e84e6SDmitry Torokhov 664d05e84e6SDmitry Torokhov /***************************************************************************** 665df561fcdSOndrej Zary * IRTOUCH Part 666df561fcdSOndrej Zary */ 667df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 668df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 669df561fcdSOndrej Zary { 670df561fcdSOndrej Zary dev->x = (pkt[3] << 8) | pkt[2]; 671df561fcdSOndrej Zary dev->y = (pkt[5] << 8) | pkt[4]; 672df561fcdSOndrej Zary dev->touch = (pkt[1] & 0x03) ? 1 : 0; 673df561fcdSOndrej Zary 674df561fcdSOndrej Zary return 1; 675df561fcdSOndrej Zary } 676df561fcdSOndrej Zary #endif 677df561fcdSOndrej Zary 678dbe1420bSPetr Štetiar /***************************************************************************** 67938771bb4SPetr Štetiar * ET&T TC5UH/TC4UM part 680dbe1420bSPetr Štetiar */ 68138771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 68238771bb4SPetr Štetiar static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 683dbe1420bSPetr Štetiar { 684dbe1420bSPetr Štetiar dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 685dbe1420bSPetr Štetiar dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 686dbe1420bSPetr Štetiar dev->touch = pkt[0] & 0x01; 687dbe1420bSPetr Štetiar 688dbe1420bSPetr Štetiar return 1; 689dbe1420bSPetr Štetiar } 690dbe1420bSPetr Štetiar #endif 691df561fcdSOndrej Zary 692df561fcdSOndrej Zary /***************************************************************************** 693a14a8401SOndrej Zary * IdealTEK URTC1000 Part 694a14a8401SOndrej Zary */ 695a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 69662aa366dSDaniel Ritz #ifndef MULTI_PACKET 69762aa366dSDaniel Ritz #define MULTI_PACKET 69862aa366dSDaniel Ritz #endif 699a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len) 700a14a8401SOndrej Zary { 701a14a8401SOndrej Zary if (buf[0] & 0x80) 702a14a8401SOndrej Zary return 5; 703a14a8401SOndrej Zary if (buf[0] == 0x01) 704a14a8401SOndrej Zary return len; 705a14a8401SOndrej Zary return 0; 706a14a8401SOndrej Zary } 707a14a8401SOndrej Zary 708a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 709a14a8401SOndrej Zary { 710a14a8401SOndrej Zary switch (pkt[0] & 0x98) { 711a14a8401SOndrej Zary case 0x88: 712a14a8401SOndrej Zary /* touch data in IdealTEK mode */ 713a14a8401SOndrej Zary dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 714a14a8401SOndrej Zary dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 715a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 716a14a8401SOndrej Zary return 1; 717a14a8401SOndrej Zary 718a14a8401SOndrej Zary case 0x98: 719a14a8401SOndrej Zary /* touch data in MT emulation mode */ 720a14a8401SOndrej Zary dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 721a14a8401SOndrej Zary dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 722a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 723a14a8401SOndrej Zary return 1; 724a14a8401SOndrej Zary 725a14a8401SOndrej Zary default: 726a14a8401SOndrej Zary return 0; 727a14a8401SOndrej Zary } 728a14a8401SOndrej Zary } 729a14a8401SOndrej Zary #endif 730a14a8401SOndrej Zary 7319d5657dbSIlya Frolov /***************************************************************************** 7329d5657dbSIlya Frolov * General Touch Part 7339d5657dbSIlya Frolov */ 7349d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 7359d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7369d5657dbSIlya Frolov { 737eb083ba2SRoy Yin dev->x = (pkt[2] << 8) | pkt[1]; 738eb083ba2SRoy Yin dev->y = (pkt[4] << 8) | pkt[3]; 7399d5657dbSIlya Frolov dev->press = pkt[5] & 0xff; 7409d5657dbSIlya Frolov dev->touch = pkt[0] & 0x01; 7419d5657dbSIlya Frolov 7429d5657dbSIlya Frolov return 1; 7439d5657dbSIlya Frolov } 7449d5657dbSIlya Frolov #endif 745a14a8401SOndrej Zary 746a14a8401SOndrej Zary /***************************************************************************** 74714e40206SJerrold Jones * GoTop Part 74814e40206SJerrold Jones */ 74914e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 75014e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 75114e40206SJerrold Jones { 75214e40206SJerrold Jones dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 75314e40206SJerrold Jones dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 75414e40206SJerrold Jones dev->touch = pkt[0] & 0x01; 755f7370699SJim Persson 756f7370699SJim Persson return 1; 757f7370699SJim Persson } 758f7370699SJim Persson #endif 759f7370699SJim Persson 760f7370699SJim Persson /***************************************************************************** 761f7370699SJim Persson * JASTEC Part 762f7370699SJim Persson */ 763f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 764f7370699SJim Persson static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 765f7370699SJim Persson { 766f7370699SJim Persson dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); 767f7370699SJim Persson dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); 768f7370699SJim Persson dev->touch = (pkt[0] & 0x40) >> 6; 769f7370699SJim Persson 77014e40206SJerrold Jones return 1; 77114e40206SJerrold Jones } 77214e40206SJerrold Jones #endif 77314e40206SJerrold Jones 7742330ed18SDaniel Silverstone /***************************************************************************** 7752330ed18SDaniel Silverstone * Zytronic Part 7762330ed18SDaniel Silverstone */ 7772330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 7782330ed18SDaniel Silverstone static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7792330ed18SDaniel Silverstone { 7800a5ebc88SGreg Kroah-Hartman struct usb_interface *intf = dev->interface; 781b741ab9dSGreg Kroah-Hartman 7822330ed18SDaniel Silverstone switch (pkt[0]) { 7832330ed18SDaniel Silverstone case 0x3A: /* command response */ 7840a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]); 7852330ed18SDaniel Silverstone break; 7862330ed18SDaniel Silverstone 7872330ed18SDaniel Silverstone case 0xC0: /* down */ 7882330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 7892330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 7902330ed18SDaniel Silverstone dev->touch = 1; 7910a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y); 7922330ed18SDaniel Silverstone return 1; 7932330ed18SDaniel Silverstone 7942330ed18SDaniel Silverstone case 0x80: /* up */ 7952330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 7962330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 7972330ed18SDaniel Silverstone dev->touch = 0; 7980a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y); 7992330ed18SDaniel Silverstone return 1; 8002330ed18SDaniel Silverstone 8012330ed18SDaniel Silverstone default: 8020a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]); 8032330ed18SDaniel Silverstone break; 8042330ed18SDaniel Silverstone } 8052330ed18SDaniel Silverstone 8062330ed18SDaniel Silverstone return 0; 8072330ed18SDaniel Silverstone } 8082330ed18SDaniel Silverstone #endif 80914e40206SJerrold Jones 81014e40206SJerrold Jones /***************************************************************************** 8115197424cSOndrej Zary * NEXIO Part 8125197424cSOndrej Zary */ 8135197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 8145197424cSOndrej Zary 8155197424cSOndrej Zary #define NEXIO_TIMEOUT 5000 8165197424cSOndrej Zary #define NEXIO_BUFSIZE 1024 8175197424cSOndrej Zary #define NEXIO_THRESHOLD 50 8185197424cSOndrej Zary 8195197424cSOndrej Zary struct nexio_priv { 8205197424cSOndrej Zary struct urb *ack; 8215197424cSOndrej Zary unsigned char *ack_buf; 8225197424cSOndrej Zary }; 8235197424cSOndrej Zary 8245197424cSOndrej Zary struct nexio_touch_packet { 8255197424cSOndrej Zary u8 flags; /* 0xe1 = touch, 0xe1 = release */ 8265197424cSOndrej Zary __be16 data_len; /* total bytes of touch data */ 8275197424cSOndrej Zary __be16 x_len; /* bytes for X axis */ 8285197424cSOndrej Zary __be16 y_len; /* bytes for Y axis */ 8295197424cSOndrej Zary u8 data[]; 8305197424cSOndrej Zary } __attribute__ ((packed)); 8315197424cSOndrej Zary 8325197424cSOndrej Zary static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; 8335197424cSOndrej Zary static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; 8345197424cSOndrej Zary 8355197424cSOndrej Zary static void nexio_ack_complete(struct urb *urb) 8365197424cSOndrej Zary { 8375197424cSOndrej Zary } 8385197424cSOndrej Zary 839a8aef622SOliver Neukum static int nexio_alloc(struct usbtouch_usb *usbtouch) 840a8aef622SOliver Neukum { 841a8aef622SOliver Neukum struct nexio_priv *priv; 842a8aef622SOliver Neukum int ret = -ENOMEM; 843a8aef622SOliver Neukum 844a8aef622SOliver Neukum usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); 845a8aef622SOliver Neukum if (!usbtouch->priv) 846a8aef622SOliver Neukum goto out_buf; 847a8aef622SOliver Neukum 848a8aef622SOliver Neukum priv = usbtouch->priv; 849a8aef622SOliver Neukum 850a8aef622SOliver Neukum priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), 851a8aef622SOliver Neukum GFP_KERNEL); 852a8aef622SOliver Neukum if (!priv->ack_buf) 853a8aef622SOliver Neukum goto err_priv; 854a8aef622SOliver Neukum 855a8aef622SOliver Neukum priv->ack = usb_alloc_urb(0, GFP_KERNEL); 856a8aef622SOliver Neukum if (!priv->ack) { 8570a5ebc88SGreg Kroah-Hartman dev_dbg(&usbtouch->interface->dev, 858b741ab9dSGreg Kroah-Hartman "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__); 859a8aef622SOliver Neukum goto err_ack_buf; 860a8aef622SOliver Neukum } 861a8aef622SOliver Neukum 862a8aef622SOliver Neukum return 0; 863a8aef622SOliver Neukum 864a8aef622SOliver Neukum err_ack_buf: 865a8aef622SOliver Neukum kfree(priv->ack_buf); 866a8aef622SOliver Neukum err_priv: 867a8aef622SOliver Neukum kfree(priv); 868a8aef622SOliver Neukum out_buf: 869a8aef622SOliver Neukum return ret; 870a8aef622SOliver Neukum } 871a8aef622SOliver Neukum 8725197424cSOndrej Zary static int nexio_init(struct usbtouch_usb *usbtouch) 8735197424cSOndrej Zary { 8745197424cSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 8755197424cSOndrej Zary struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; 876a8aef622SOliver Neukum struct nexio_priv *priv = usbtouch->priv; 8775197424cSOndrej Zary int ret = -ENOMEM; 8785197424cSOndrej Zary int actual_len, i; 8795197424cSOndrej Zary unsigned char *buf; 8805197424cSOndrej Zary char *firmware_ver = NULL, *device_name = NULL; 8815197424cSOndrej Zary int input_ep = 0, output_ep = 0; 8825197424cSOndrej Zary 8835197424cSOndrej Zary /* find first input and output endpoint */ 8845197424cSOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) { 8855197424cSOndrej Zary if (!input_ep && 8865197424cSOndrej Zary usb_endpoint_dir_in(&interface->endpoint[i].desc)) 8875197424cSOndrej Zary input_ep = interface->endpoint[i].desc.bEndpointAddress; 8885197424cSOndrej Zary if (!output_ep && 8895197424cSOndrej Zary usb_endpoint_dir_out(&interface->endpoint[i].desc)) 8905197424cSOndrej Zary output_ep = interface->endpoint[i].desc.bEndpointAddress; 8915197424cSOndrej Zary } 8925197424cSOndrej Zary if (!input_ep || !output_ep) 8935197424cSOndrej Zary return -ENXIO; 8945197424cSOndrej Zary 895a8aef622SOliver Neukum buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); 8965197424cSOndrej Zary if (!buf) 8975197424cSOndrej Zary goto out_buf; 8985197424cSOndrej Zary 8995197424cSOndrej Zary /* two empty reads */ 9005197424cSOndrej Zary for (i = 0; i < 2; i++) { 9015197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 9025197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 9035197424cSOndrej Zary NEXIO_TIMEOUT); 9045197424cSOndrej Zary if (ret < 0) 9055197424cSOndrej Zary goto out_buf; 9065197424cSOndrej Zary } 9075197424cSOndrej Zary 9085197424cSOndrej Zary /* send init command */ 9095197424cSOndrej Zary memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); 9105197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), 9115197424cSOndrej Zary buf, sizeof(nexio_init_pkt), &actual_len, 9125197424cSOndrej Zary NEXIO_TIMEOUT); 9135197424cSOndrej Zary if (ret < 0) 9145197424cSOndrej Zary goto out_buf; 9155197424cSOndrej Zary 9165197424cSOndrej Zary /* read replies */ 9175197424cSOndrej Zary for (i = 0; i < 3; i++) { 9185197424cSOndrej Zary memset(buf, 0, NEXIO_BUFSIZE); 9195197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 9205197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 9215197424cSOndrej Zary NEXIO_TIMEOUT); 9225197424cSOndrej Zary if (ret < 0 || actual_len < 1 || buf[1] != actual_len) 9235197424cSOndrej Zary continue; 9245197424cSOndrej Zary switch (buf[0]) { 9255197424cSOndrej Zary case 0x83: /* firmware version */ 9265197424cSOndrej Zary if (!firmware_ver) 927a8aef622SOliver Neukum firmware_ver = kstrdup(&buf[2], GFP_NOIO); 9285197424cSOndrej Zary break; 9295197424cSOndrej Zary case 0x84: /* device name */ 9305197424cSOndrej Zary if (!device_name) 931a8aef622SOliver Neukum device_name = kstrdup(&buf[2], GFP_NOIO); 9325197424cSOndrej Zary break; 9335197424cSOndrej Zary } 9345197424cSOndrej Zary } 9355197424cSOndrej Zary 9365197424cSOndrej Zary printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", 9375197424cSOndrej Zary device_name, firmware_ver); 9385197424cSOndrej Zary 9395197424cSOndrej Zary kfree(firmware_ver); 9405197424cSOndrej Zary kfree(device_name); 9415197424cSOndrej Zary 9425197424cSOndrej Zary usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), 9435197424cSOndrej Zary priv->ack_buf, sizeof(nexio_ack_pkt), 9445197424cSOndrej Zary nexio_ack_complete, usbtouch); 9455197424cSOndrej Zary ret = 0; 9465197424cSOndrej Zary 9475197424cSOndrej Zary out_buf: 9485197424cSOndrej Zary kfree(buf); 9495197424cSOndrej Zary return ret; 9505197424cSOndrej Zary } 9515197424cSOndrej Zary 9525197424cSOndrej Zary static void nexio_exit(struct usbtouch_usb *usbtouch) 9535197424cSOndrej Zary { 9545197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 9555197424cSOndrej Zary 9565197424cSOndrej Zary usb_kill_urb(priv->ack); 9575197424cSOndrej Zary usb_free_urb(priv->ack); 9585197424cSOndrej Zary kfree(priv->ack_buf); 9595197424cSOndrej Zary kfree(priv); 9605197424cSOndrej Zary } 9615197424cSOndrej Zary 9625197424cSOndrej Zary static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) 9635197424cSOndrej Zary { 9645197424cSOndrej Zary struct nexio_touch_packet *packet = (void *) pkt; 9655197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 9664aa5bbecSDmitry Torokhov unsigned int data_len = be16_to_cpu(packet->data_len); 9674aa5bbecSDmitry Torokhov unsigned int x_len = be16_to_cpu(packet->x_len); 9684aa5bbecSDmitry Torokhov unsigned int y_len = be16_to_cpu(packet->y_len); 9694aa5bbecSDmitry Torokhov int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; 9705197424cSOndrej Zary 9715197424cSOndrej Zary /* got touch data? */ 9725197424cSOndrej Zary if ((pkt[0] & 0xe0) != 0xe0) 9735197424cSOndrej Zary return 0; 9745197424cSOndrej Zary 9754aa5bbecSDmitry Torokhov if (data_len > 0xff) 9764aa5bbecSDmitry Torokhov data_len -= 0x100; 9774aa5bbecSDmitry Torokhov if (x_len > 0xff) 9784aa5bbecSDmitry Torokhov x_len -= 0x80; 979388bbcadSOndrej Zary 9805197424cSOndrej Zary /* send ACK */ 9815197424cSOndrej Zary ret = usb_submit_urb(priv->ack, GFP_ATOMIC); 9825197424cSOndrej Zary 9835197424cSOndrej Zary if (!usbtouch->type->max_xc) { 9844aa5bbecSDmitry Torokhov usbtouch->type->max_xc = 2 * x_len; 9854aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_X, 9864aa5bbecSDmitry Torokhov 0, usbtouch->type->max_xc, 0, 0); 9874aa5bbecSDmitry Torokhov usbtouch->type->max_yc = 2 * y_len; 9884aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_Y, 9894aa5bbecSDmitry Torokhov 0, usbtouch->type->max_yc, 0, 0); 9905197424cSOndrej Zary } 9915197424cSOndrej Zary /* 9925197424cSOndrej Zary * The device reports state of IR sensors on X and Y axes. 9935197424cSOndrej Zary * Each byte represents "darkness" percentage (0-100) of one element. 9945197424cSOndrej Zary * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. 9955197424cSOndrej Zary * This also means that there's a limited multi-touch capability but 9965197424cSOndrej Zary * it's disabled (and untested) here as there's no X driver for that. 9975197424cSOndrej Zary */ 9985197424cSOndrej Zary begin_x = end_x = begin_y = end_y = -1; 9994aa5bbecSDmitry Torokhov for (x = 0; x < x_len; x++) { 10005197424cSOndrej Zary if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { 10015197424cSOndrej Zary begin_x = x; 10025197424cSOndrej Zary continue; 10035197424cSOndrej Zary } 10045197424cSOndrej Zary if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { 10055197424cSOndrej Zary end_x = x - 1; 10064aa5bbecSDmitry Torokhov for (y = x_len; y < data_len; y++) { 10075197424cSOndrej Zary if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { 10084aa5bbecSDmitry Torokhov begin_y = y - x_len; 10095197424cSOndrej Zary continue; 10105197424cSOndrej Zary } 10115197424cSOndrej Zary if (end_y == -1 && 10125197424cSOndrej Zary begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { 10134aa5bbecSDmitry Torokhov end_y = y - 1 - x_len; 10145197424cSOndrej Zary w = end_x - begin_x; 10155197424cSOndrej Zary h = end_y - begin_y; 10165197424cSOndrej Zary #if 0 10175197424cSOndrej Zary /* multi-touch */ 10185197424cSOndrej Zary input_report_abs(usbtouch->input, 10195197424cSOndrej Zary ABS_MT_TOUCH_MAJOR, max(w,h)); 10205197424cSOndrej Zary input_report_abs(usbtouch->input, 10215197424cSOndrej Zary ABS_MT_TOUCH_MINOR, min(x,h)); 10225197424cSOndrej Zary input_report_abs(usbtouch->input, 10235197424cSOndrej Zary ABS_MT_POSITION_X, 2*begin_x+w); 10245197424cSOndrej Zary input_report_abs(usbtouch->input, 10255197424cSOndrej Zary ABS_MT_POSITION_Y, 2*begin_y+h); 10265197424cSOndrej Zary input_report_abs(usbtouch->input, 10275197424cSOndrej Zary ABS_MT_ORIENTATION, w > h); 10285197424cSOndrej Zary input_mt_sync(usbtouch->input); 10295197424cSOndrej Zary #endif 10305197424cSOndrej Zary /* single touch */ 10315197424cSOndrej Zary usbtouch->x = 2 * begin_x + w; 10325197424cSOndrej Zary usbtouch->y = 2 * begin_y + h; 10335197424cSOndrej Zary usbtouch->touch = packet->flags & 0x01; 10345197424cSOndrej Zary begin_y = end_y = -1; 10355197424cSOndrej Zary return 1; 10365197424cSOndrej Zary } 10375197424cSOndrej Zary } 10385197424cSOndrej Zary begin_x = end_x = -1; 10395197424cSOndrej Zary } 10405197424cSOndrej Zary 10415197424cSOndrej Zary } 10425197424cSOndrej Zary return 0; 10435197424cSOndrej Zary } 10445197424cSOndrej Zary #endif 10455197424cSOndrej Zary 10465197424cSOndrej Zary 10475197424cSOndrej Zary /***************************************************************************** 1048d2cc817aSMichael Gebetsroither * ELO part 1049d2cc817aSMichael Gebetsroither */ 1050d2cc817aSMichael Gebetsroither 1051d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 1052d2cc817aSMichael Gebetsroither 1053d2cc817aSMichael Gebetsroither static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 1054d2cc817aSMichael Gebetsroither { 1055d2cc817aSMichael Gebetsroither dev->x = (pkt[3] << 8) | pkt[2]; 1056d2cc817aSMichael Gebetsroither dev->y = (pkt[5] << 8) | pkt[4]; 1057d2cc817aSMichael Gebetsroither dev->touch = pkt[6] > 0; 1058d2cc817aSMichael Gebetsroither dev->press = pkt[6]; 1059d2cc817aSMichael Gebetsroither 1060d2cc817aSMichael Gebetsroither return 1; 1061d2cc817aSMichael Gebetsroither } 1062d2cc817aSMichael Gebetsroither #endif 1063d2cc817aSMichael Gebetsroither 1064d2cc817aSMichael Gebetsroither 1065d2cc817aSMichael Gebetsroither /***************************************************************************** 1066d05e84e6SDmitry Torokhov * the different device descriptors 1067d05e84e6SDmitry Torokhov */ 106862aa366dSDaniel Ritz #ifdef MULTI_PACKET 106962aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 107062aa366dSDaniel Ritz unsigned char *pkt, int len); 107162aa366dSDaniel Ritz #endif 107262aa366dSDaniel Ritz 1073d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = { 1074d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 1075d2cc817aSMichael Gebetsroither [DEVTYPE_ELO] = { 1076d2cc817aSMichael Gebetsroither .min_xc = 0x0, 1077d2cc817aSMichael Gebetsroither .max_xc = 0x0fff, 1078d2cc817aSMichael Gebetsroither .min_yc = 0x0, 1079d2cc817aSMichael Gebetsroither .max_yc = 0x0fff, 1080d2cc817aSMichael Gebetsroither .max_press = 0xff, 1081d2cc817aSMichael Gebetsroither .rept_size = 8, 1082d2cc817aSMichael Gebetsroither .read_data = elo_read_data, 1083d2cc817aSMichael Gebetsroither }, 1084d2cc817aSMichael Gebetsroither #endif 1085d2cc817aSMichael Gebetsroither 1086c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 1087d05e84e6SDmitry Torokhov [DEVTYPE_EGALAX] = { 1088d05e84e6SDmitry Torokhov .min_xc = 0x0, 1089d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 1090d05e84e6SDmitry Torokhov .min_yc = 0x0, 1091d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 1092d05e84e6SDmitry Torokhov .rept_size = 16, 1093d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1094d05e84e6SDmitry Torokhov .get_pkt_len = egalax_get_pkt_len, 1095d05e84e6SDmitry Torokhov .read_data = egalax_read_data, 1096037a833eSForest Bond .init = egalax_init, 1097d05e84e6SDmitry Torokhov }, 1098d05e84e6SDmitry Torokhov #endif 1099d05e84e6SDmitry Torokhov 1100c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 1101d05e84e6SDmitry Torokhov [DEVTYPE_PANJIT] = { 1102d05e84e6SDmitry Torokhov .min_xc = 0x0, 1103d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1104d05e84e6SDmitry Torokhov .min_yc = 0x0, 1105d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1106d05e84e6SDmitry Torokhov .rept_size = 8, 1107d05e84e6SDmitry Torokhov .read_data = panjit_read_data, 1108d05e84e6SDmitry Torokhov }, 1109d05e84e6SDmitry Torokhov #endif 1110d05e84e6SDmitry Torokhov 1111c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 1112d05e84e6SDmitry Torokhov [DEVTYPE_3M] = { 1113d05e84e6SDmitry Torokhov .min_xc = 0x0, 1114d05e84e6SDmitry Torokhov .max_xc = 0x4000, 1115d05e84e6SDmitry Torokhov .min_yc = 0x0, 1116d05e84e6SDmitry Torokhov .max_yc = 0x4000, 1117d05e84e6SDmitry Torokhov .rept_size = 11, 1118d05e84e6SDmitry Torokhov .read_data = mtouch_read_data, 1119d05e84e6SDmitry Torokhov .init = mtouch_init, 1120d05e84e6SDmitry Torokhov }, 1121d05e84e6SDmitry Torokhov #endif 1122d05e84e6SDmitry Torokhov 1123c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 1124d05e84e6SDmitry Torokhov [DEVTYPE_ITM] = { 1125d05e84e6SDmitry Torokhov .min_xc = 0x0, 1126d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1127d05e84e6SDmitry Torokhov .min_yc = 0x0, 1128d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1129d05e84e6SDmitry Torokhov .max_press = 0xff, 1130d05e84e6SDmitry Torokhov .rept_size = 8, 1131d05e84e6SDmitry Torokhov .read_data = itm_read_data, 1132d05e84e6SDmitry Torokhov }, 1133d05e84e6SDmitry Torokhov #endif 1134d05e84e6SDmitry Torokhov 1135c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 1136d05e84e6SDmitry Torokhov [DEVTYPE_ETURBO] = { 1137d05e84e6SDmitry Torokhov .min_xc = 0x0, 1138d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 1139d05e84e6SDmitry Torokhov .min_yc = 0x0, 1140d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 1141d05e84e6SDmitry Torokhov .rept_size = 8, 1142d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1143d05e84e6SDmitry Torokhov .get_pkt_len = eturbo_get_pkt_len, 1144d05e84e6SDmitry Torokhov .read_data = eturbo_read_data, 1145d05e84e6SDmitry Torokhov }, 1146d05e84e6SDmitry Torokhov #endif 1147d05e84e6SDmitry Torokhov 1148c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 1149d05e84e6SDmitry Torokhov [DEVTYPE_GUNZE] = { 1150d05e84e6SDmitry Torokhov .min_xc = 0x0, 1151d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1152d05e84e6SDmitry Torokhov .min_yc = 0x0, 1153d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1154d05e84e6SDmitry Torokhov .rept_size = 4, 1155d05e84e6SDmitry Torokhov .read_data = gunze_read_data, 1156d05e84e6SDmitry Torokhov }, 1157d05e84e6SDmitry Torokhov #endif 1158d05e84e6SDmitry Torokhov 1159c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 1160d05e84e6SDmitry Torokhov [DEVTYPE_DMC_TSC10] = { 1161d05e84e6SDmitry Torokhov .min_xc = 0x0, 1162d05e84e6SDmitry Torokhov .max_xc = 0x03ff, 1163d05e84e6SDmitry Torokhov .min_yc = 0x0, 1164d05e84e6SDmitry Torokhov .max_yc = 0x03ff, 1165d05e84e6SDmitry Torokhov .rept_size = 5, 1166d05e84e6SDmitry Torokhov .init = dmc_tsc10_init, 1167d05e84e6SDmitry Torokhov .read_data = dmc_tsc10_read_data, 1168d05e84e6SDmitry Torokhov }, 1169d05e84e6SDmitry Torokhov #endif 1170df561fcdSOndrej Zary 1171df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 1172df561fcdSOndrej Zary [DEVTYPE_IRTOUCH] = { 1173df561fcdSOndrej Zary .min_xc = 0x0, 1174df561fcdSOndrej Zary .max_xc = 0x0fff, 1175df561fcdSOndrej Zary .min_yc = 0x0, 1176df561fcdSOndrej Zary .max_yc = 0x0fff, 1177df561fcdSOndrej Zary .rept_size = 8, 1178df561fcdSOndrej Zary .read_data = irtouch_read_data, 1179df561fcdSOndrej Zary }, 1180df561fcdSOndrej Zary #endif 1181a14a8401SOndrej Zary 1182a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 1183a14a8401SOndrej Zary [DEVTYPE_IDEALTEK] = { 1184a14a8401SOndrej Zary .min_xc = 0x0, 1185a14a8401SOndrej Zary .max_xc = 0x0fff, 1186a14a8401SOndrej Zary .min_yc = 0x0, 1187a14a8401SOndrej Zary .max_yc = 0x0fff, 1188a14a8401SOndrej Zary .rept_size = 8, 1189a14a8401SOndrej Zary .process_pkt = usbtouch_process_multi, 1190a14a8401SOndrej Zary .get_pkt_len = idealtek_get_pkt_len, 1191a14a8401SOndrej Zary .read_data = idealtek_read_data, 1192a14a8401SOndrej Zary }, 1193a14a8401SOndrej Zary #endif 11949d5657dbSIlya Frolov 11959d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 11969d5657dbSIlya Frolov [DEVTYPE_GENERAL_TOUCH] = { 11979d5657dbSIlya Frolov .min_xc = 0x0, 1198eb083ba2SRoy Yin .max_xc = 0x7fff, 11999d5657dbSIlya Frolov .min_yc = 0x0, 1200eb083ba2SRoy Yin .max_yc = 0x7fff, 12019d5657dbSIlya Frolov .rept_size = 7, 12029d5657dbSIlya Frolov .read_data = general_touch_read_data, 120314e40206SJerrold Jones }, 12049d5657dbSIlya Frolov #endif 12059d5657dbSIlya Frolov 120614e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 120714e40206SJerrold Jones [DEVTYPE_GOTOP] = { 120814e40206SJerrold Jones .min_xc = 0x0, 120914e40206SJerrold Jones .max_xc = 0x03ff, 121014e40206SJerrold Jones .min_yc = 0x0, 121114e40206SJerrold Jones .max_yc = 0x03ff, 121214e40206SJerrold Jones .rept_size = 4, 121314e40206SJerrold Jones .read_data = gotop_read_data, 121414e40206SJerrold Jones }, 121514e40206SJerrold Jones #endif 1216f7370699SJim Persson 1217f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 1218f7370699SJim Persson [DEVTYPE_JASTEC] = { 1219f7370699SJim Persson .min_xc = 0x0, 1220f7370699SJim Persson .max_xc = 0x0fff, 1221f7370699SJim Persson .min_yc = 0x0, 1222f7370699SJim Persson .max_yc = 0x0fff, 1223f7370699SJim Persson .rept_size = 4, 1224f7370699SJim Persson .read_data = jastec_read_data, 1225f7370699SJim Persson }, 1226f7370699SJim Persson #endif 12279e3b2583SFlorian Echtler 12289e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 12299e3b2583SFlorian Echtler [DEVTYPE_E2I] = { 12309e3b2583SFlorian Echtler .min_xc = 0x0, 12319e3b2583SFlorian Echtler .max_xc = 0x7fff, 12329e3b2583SFlorian Echtler .min_yc = 0x0, 12339e3b2583SFlorian Echtler .max_yc = 0x7fff, 12349e3b2583SFlorian Echtler .rept_size = 6, 12359e3b2583SFlorian Echtler .init = e2i_init, 12369e3b2583SFlorian Echtler .read_data = e2i_read_data, 12379e3b2583SFlorian Echtler }, 12389e3b2583SFlorian Echtler #endif 12392330ed18SDaniel Silverstone 12402330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 12412330ed18SDaniel Silverstone [DEVTYPE_ZYTRONIC] = { 12422330ed18SDaniel Silverstone .min_xc = 0x0, 12432330ed18SDaniel Silverstone .max_xc = 0x03ff, 12442330ed18SDaniel Silverstone .min_yc = 0x0, 12452330ed18SDaniel Silverstone .max_yc = 0x03ff, 12462330ed18SDaniel Silverstone .rept_size = 5, 12472330ed18SDaniel Silverstone .read_data = zytronic_read_data, 12482330ed18SDaniel Silverstone .irq_always = true, 12492330ed18SDaniel Silverstone }, 12502330ed18SDaniel Silverstone #endif 1251dbe1420bSPetr Štetiar 125238771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 125338771bb4SPetr Štetiar [DEVTYPE_TC45USB] = { 1254dbe1420bSPetr Štetiar .min_xc = 0x0, 1255dbe1420bSPetr Štetiar .max_xc = 0x0fff, 1256dbe1420bSPetr Štetiar .min_yc = 0x0, 1257dbe1420bSPetr Štetiar .max_yc = 0x0fff, 1258dbe1420bSPetr Štetiar .rept_size = 5, 125938771bb4SPetr Štetiar .read_data = tc45usb_read_data, 1260dbe1420bSPetr Štetiar }, 1261dbe1420bSPetr Štetiar #endif 12625197424cSOndrej Zary 12635197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 12645197424cSOndrej Zary [DEVTYPE_NEXIO] = { 1265388bbcadSOndrej Zary .rept_size = 1024, 12665197424cSOndrej Zary .irq_always = true, 12675197424cSOndrej Zary .read_data = nexio_read_data, 1268a8aef622SOliver Neukum .alloc = nexio_alloc, 12695197424cSOndrej Zary .init = nexio_init, 12705197424cSOndrej Zary .exit = nexio_exit, 12715197424cSOndrej Zary }, 12725197424cSOndrej Zary #endif 1273aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 1274aa87512fSArmando Visconti [DEVTYPE_ETOUCH] = { 1275aa87512fSArmando Visconti .min_xc = 0x0, 1276aa87512fSArmando Visconti .max_xc = 0x07ff, 1277aa87512fSArmando Visconti .min_yc = 0x0, 1278aa87512fSArmando Visconti .max_yc = 0x07ff, 1279aa87512fSArmando Visconti .rept_size = 16, 1280aa87512fSArmando Visconti .process_pkt = usbtouch_process_multi, 1281aa87512fSArmando Visconti .get_pkt_len = etouch_get_pkt_len, 1282aa87512fSArmando Visconti .read_data = etouch_read_data, 1283aa87512fSArmando Visconti }, 1284aa87512fSArmando Visconti #endif 1285d05e84e6SDmitry Torokhov }; 1286d05e84e6SDmitry Torokhov 1287d05e84e6SDmitry Torokhov 1288d05e84e6SDmitry Torokhov /***************************************************************************** 1289d05e84e6SDmitry Torokhov * Generic Part 1290d05e84e6SDmitry Torokhov */ 1291d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 1292d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1293d05e84e6SDmitry Torokhov { 1294d05e84e6SDmitry Torokhov struct usbtouch_device_info *type = usbtouch->type; 1295d05e84e6SDmitry Torokhov 1296d05e84e6SDmitry Torokhov if (!type->read_data(usbtouch, pkt)) 1297d05e84e6SDmitry Torokhov return; 1298d05e84e6SDmitry Torokhov 1299d05e84e6SDmitry Torokhov input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 1300d05e84e6SDmitry Torokhov 1301d05e84e6SDmitry Torokhov if (swap_xy) { 1302d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 1303d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 1304d05e84e6SDmitry Torokhov } else { 1305d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 1306d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 1307d05e84e6SDmitry Torokhov } 1308d05e84e6SDmitry Torokhov if (type->max_press) 1309d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 1310d05e84e6SDmitry Torokhov input_sync(usbtouch->input); 1311d05e84e6SDmitry Torokhov } 1312d05e84e6SDmitry Torokhov 1313d05e84e6SDmitry Torokhov 1314d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET 1315d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 1316d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1317d05e84e6SDmitry Torokhov { 1318d05e84e6SDmitry Torokhov unsigned char *buffer; 1319d05e84e6SDmitry Torokhov int pkt_len, pos, buf_len, tmp; 1320d05e84e6SDmitry Torokhov 1321d05e84e6SDmitry Torokhov /* process buffer */ 1322d05e84e6SDmitry Torokhov if (unlikely(usbtouch->buf_len)) { 1323d05e84e6SDmitry Torokhov /* try to get size */ 1324d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1325d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1326d05e84e6SDmitry Torokhov 1327d05e84e6SDmitry Torokhov /* drop? */ 1328d05e84e6SDmitry Torokhov if (unlikely(!pkt_len)) 1329d05e84e6SDmitry Torokhov goto out_flush_buf; 1330d05e84e6SDmitry Torokhov 1331d05e84e6SDmitry Torokhov /* need to append -pkt_len bytes before able to get size */ 1332d05e84e6SDmitry Torokhov if (unlikely(pkt_len < 0)) { 1333d05e84e6SDmitry Torokhov int append = -pkt_len; 1334d05e84e6SDmitry Torokhov if (unlikely(append > len)) 1335d05e84e6SDmitry Torokhov append = len; 1336d05e84e6SDmitry Torokhov if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 1337d05e84e6SDmitry Torokhov goto out_flush_buf; 1338d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 1339d05e84e6SDmitry Torokhov usbtouch->buf_len += append; 1340d05e84e6SDmitry Torokhov 1341d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1342d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1343d05e84e6SDmitry Torokhov if (pkt_len < 0) 1344d05e84e6SDmitry Torokhov return; 1345d05e84e6SDmitry Torokhov } 1346d05e84e6SDmitry Torokhov 1347d05e84e6SDmitry Torokhov /* append */ 1348d05e84e6SDmitry Torokhov tmp = pkt_len - usbtouch->buf_len; 1349d05e84e6SDmitry Torokhov if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 1350d05e84e6SDmitry Torokhov goto out_flush_buf; 1351d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 1352d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 1353d05e84e6SDmitry Torokhov 1354d05e84e6SDmitry Torokhov buffer = pkt + tmp; 1355d05e84e6SDmitry Torokhov buf_len = len - tmp; 1356d05e84e6SDmitry Torokhov } else { 1357d05e84e6SDmitry Torokhov buffer = pkt; 1358d05e84e6SDmitry Torokhov buf_len = len; 1359d05e84e6SDmitry Torokhov } 1360d05e84e6SDmitry Torokhov 1361d05e84e6SDmitry Torokhov /* loop over the received packet, process */ 1362d05e84e6SDmitry Torokhov pos = 0; 1363d05e84e6SDmitry Torokhov while (pos < buf_len) { 1364d05e84e6SDmitry Torokhov /* get packet len */ 136562aa366dSDaniel Ritz pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 136662aa366dSDaniel Ritz buf_len - pos); 1367d05e84e6SDmitry Torokhov 136862aa366dSDaniel Ritz /* unknown packet: skip one byte */ 136962aa366dSDaniel Ritz if (unlikely(!pkt_len)) { 137062aa366dSDaniel Ritz pos++; 137162aa366dSDaniel Ritz continue; 137262aa366dSDaniel Ritz } 1373d05e84e6SDmitry Torokhov 1374d05e84e6SDmitry Torokhov /* full packet: process */ 1375d05e84e6SDmitry Torokhov if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 1376d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 1377d05e84e6SDmitry Torokhov } else { 1378d05e84e6SDmitry Torokhov /* incomplete packet: save in buffer */ 1379d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 1380d05e84e6SDmitry Torokhov usbtouch->buf_len = buf_len - pos; 1381d05e84e6SDmitry Torokhov return; 1382d05e84e6SDmitry Torokhov } 1383d05e84e6SDmitry Torokhov pos += pkt_len; 1384d05e84e6SDmitry Torokhov } 1385d05e84e6SDmitry Torokhov 1386d05e84e6SDmitry Torokhov out_flush_buf: 1387d05e84e6SDmitry Torokhov usbtouch->buf_len = 0; 1388d05e84e6SDmitry Torokhov return; 1389d05e84e6SDmitry Torokhov } 1390d05e84e6SDmitry Torokhov #endif 1391d05e84e6SDmitry Torokhov 1392d05e84e6SDmitry Torokhov 1393d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb) 1394d05e84e6SDmitry Torokhov { 1395d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = urb->context; 13960a5ebc88SGreg Kroah-Hartman struct device *dev = &usbtouch->interface->dev; 1397d05e84e6SDmitry Torokhov int retval; 1398d05e84e6SDmitry Torokhov 1399d05e84e6SDmitry Torokhov switch (urb->status) { 1400d05e84e6SDmitry Torokhov case 0: 1401d05e84e6SDmitry Torokhov /* success */ 1402d05e84e6SDmitry Torokhov break; 1403d05e84e6SDmitry Torokhov case -ETIME: 1404d05e84e6SDmitry Torokhov /* this urb is timing out */ 1405b741ab9dSGreg Kroah-Hartman dev_dbg(dev, 1406b741ab9dSGreg Kroah-Hartman "%s - urb timed out - was the device unplugged?\n", 1407ea3e6c59SHarvey Harrison __func__); 1408d05e84e6SDmitry Torokhov return; 1409d05e84e6SDmitry Torokhov case -ECONNRESET: 1410d05e84e6SDmitry Torokhov case -ENOENT: 1411d05e84e6SDmitry Torokhov case -ESHUTDOWN: 14125197424cSOndrej Zary case -EPIPE: 1413d05e84e6SDmitry Torokhov /* this urb is terminated, clean up */ 1414b741ab9dSGreg Kroah-Hartman dev_dbg(dev, "%s - urb shutting down with status: %d\n", 1415ea3e6c59SHarvey Harrison __func__, urb->status); 1416d05e84e6SDmitry Torokhov return; 1417d05e84e6SDmitry Torokhov default: 1418b741ab9dSGreg Kroah-Hartman dev_dbg(dev, "%s - nonzero urb status received: %d\n", 1419ea3e6c59SHarvey Harrison __func__, urb->status); 1420d05e84e6SDmitry Torokhov goto exit; 1421d05e84e6SDmitry Torokhov } 1422d05e84e6SDmitry Torokhov 1423d05e84e6SDmitry Torokhov usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 1424d05e84e6SDmitry Torokhov 1425d05e84e6SDmitry Torokhov exit: 14265d9efc59SOliver Neukum usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); 1427d05e84e6SDmitry Torokhov retval = usb_submit_urb(urb, GFP_ATOMIC); 1428d05e84e6SDmitry Torokhov if (retval) 14290a5ebc88SGreg Kroah-Hartman dev_err(dev, "%s - usb_submit_urb failed with result: %d\n", 1430ea3e6c59SHarvey Harrison __func__, retval); 1431d05e84e6SDmitry Torokhov } 1432d05e84e6SDmitry Torokhov 1433d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input) 1434d05e84e6SDmitry Torokhov { 1435d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 14365d9efc59SOliver Neukum int r; 1437d05e84e6SDmitry Torokhov 1438fea4d14bSOndrej Zary usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); 1439d05e84e6SDmitry Torokhov 14405d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; 14415d9efc59SOliver Neukum if (r < 0) 14425d9efc59SOliver Neukum goto out; 14435d9efc59SOliver Neukum 14442330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) { 14455d9efc59SOliver Neukum if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { 14465d9efc59SOliver Neukum r = -EIO; 14475d9efc59SOliver Neukum goto out_put; 14485d9efc59SOliver Neukum } 14492330ed18SDaniel Silverstone } 1450d05e84e6SDmitry Torokhov 14515d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 1; 14525d9efc59SOliver Neukum out_put: 14535d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 14545d9efc59SOliver Neukum out: 14555d9efc59SOliver Neukum return r; 1456d05e84e6SDmitry Torokhov } 1457d05e84e6SDmitry Torokhov 1458d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input) 1459d05e84e6SDmitry Torokhov { 1460d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 14615d9efc59SOliver Neukum int r; 1462d05e84e6SDmitry Torokhov 14632330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) 1464d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 14655d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface); 14665d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 0; 14675d9efc59SOliver Neukum if (!r) 14685d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 1469d05e84e6SDmitry Torokhov } 1470d05e84e6SDmitry Torokhov 1471ed4299e1SOliver Neukum static int usbtouch_suspend 1472ed4299e1SOliver Neukum (struct usb_interface *intf, pm_message_t message) 1473ed4299e1SOliver Neukum { 1474ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1475ed4299e1SOliver Neukum 1476ed4299e1SOliver Neukum usb_kill_urb(usbtouch->irq); 1477ed4299e1SOliver Neukum 1478ed4299e1SOliver Neukum return 0; 1479ed4299e1SOliver Neukum } 1480ed4299e1SOliver Neukum 1481ed4299e1SOliver Neukum static int usbtouch_resume(struct usb_interface *intf) 1482ed4299e1SOliver Neukum { 1483ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1484ed4299e1SOliver Neukum struct input_dev *input = usbtouch->input; 1485ed4299e1SOliver Neukum int result = 0; 1486ed4299e1SOliver Neukum 1487ed4299e1SOliver Neukum mutex_lock(&input->mutex); 1488ed4299e1SOliver Neukum if (input->users || usbtouch->type->irq_always) 1489ed4299e1SOliver Neukum result = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1490ed4299e1SOliver Neukum mutex_unlock(&input->mutex); 1491ed4299e1SOliver Neukum 1492ed4299e1SOliver Neukum return result; 1493ed4299e1SOliver Neukum } 1494d05e84e6SDmitry Torokhov 1495a8aef622SOliver Neukum static int usbtouch_reset_resume(struct usb_interface *intf) 1496a8aef622SOliver Neukum { 1497a8aef622SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1498a8aef622SOliver Neukum struct input_dev *input = usbtouch->input; 1499a8aef622SOliver Neukum int err = 0; 1500a8aef622SOliver Neukum 1501a8aef622SOliver Neukum /* reinit the device */ 1502a8aef622SOliver Neukum if (usbtouch->type->init) { 1503a8aef622SOliver Neukum err = usbtouch->type->init(usbtouch); 1504a8aef622SOliver Neukum if (err) { 15050a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, 1506b741ab9dSGreg Kroah-Hartman "%s - type->init() failed, err: %d\n", 1507a8aef622SOliver Neukum __func__, err); 1508a8aef622SOliver Neukum return err; 1509a8aef622SOliver Neukum } 1510a8aef622SOliver Neukum } 1511a8aef622SOliver Neukum 1512a8aef622SOliver Neukum /* restart IO if needed */ 1513a8aef622SOliver Neukum mutex_lock(&input->mutex); 1514a8aef622SOliver Neukum if (input->users) 1515a8aef622SOliver Neukum err = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1516a8aef622SOliver Neukum mutex_unlock(&input->mutex); 1517a8aef622SOliver Neukum 1518a8aef622SOliver Neukum return err; 1519a8aef622SOliver Neukum } 1520a8aef622SOliver Neukum 1521d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev, 1522d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch) 1523d05e84e6SDmitry Torokhov { 1524997ea58eSDaniel Mack usb_free_coherent(udev, usbtouch->type->rept_size, 1525d05e84e6SDmitry Torokhov usbtouch->data, usbtouch->data_dma); 1526d05e84e6SDmitry Torokhov kfree(usbtouch->buffer); 1527d05e84e6SDmitry Torokhov } 1528d05e84e6SDmitry Torokhov 1529f4a5e359SOndrej Zary static struct usb_endpoint_descriptor * 1530f4a5e359SOndrej Zary usbtouch_get_input_endpoint(struct usb_host_interface *interface) 1531f4a5e359SOndrej Zary { 1532f4a5e359SOndrej Zary int i; 1533f4a5e359SOndrej Zary 1534f4a5e359SOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) 1535f4a5e359SOndrej Zary if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) 1536f4a5e359SOndrej Zary return &interface->endpoint[i].desc; 1537f4a5e359SOndrej Zary 1538f4a5e359SOndrej Zary return NULL; 1539f4a5e359SOndrej Zary } 1540d05e84e6SDmitry Torokhov 1541d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf, 1542d05e84e6SDmitry Torokhov const struct usb_device_id *id) 1543d05e84e6SDmitry Torokhov { 1544d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch; 1545d05e84e6SDmitry Torokhov struct input_dev *input_dev; 1546d05e84e6SDmitry Torokhov struct usb_endpoint_descriptor *endpoint; 1547d05e84e6SDmitry Torokhov struct usb_device *udev = interface_to_usbdev(intf); 1548d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 1549d05e84e6SDmitry Torokhov int err = -ENOMEM; 1550d05e84e6SDmitry Torokhov 1551ec42d448SDaniel Ritz /* some devices are ignored */ 1552ec42d448SDaniel Ritz if (id->driver_info == DEVTYPE_IGNORE) 1553ec42d448SDaniel Ritz return -ENODEV; 1554ec42d448SDaniel Ritz 1555f4a5e359SOndrej Zary endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); 1556f4a5e359SOndrej Zary if (!endpoint) 1557f4a5e359SOndrej Zary return -ENXIO; 1558d05e84e6SDmitry Torokhov 1559d05e84e6SDmitry Torokhov usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 1560d05e84e6SDmitry Torokhov input_dev = input_allocate_device(); 1561d05e84e6SDmitry Torokhov if (!usbtouch || !input_dev) 1562d05e84e6SDmitry Torokhov goto out_free; 1563d05e84e6SDmitry Torokhov 1564d05e84e6SDmitry Torokhov type = &usbtouch_dev_info[id->driver_info]; 1565d05e84e6SDmitry Torokhov usbtouch->type = type; 1566d05e84e6SDmitry Torokhov if (!type->process_pkt) 1567d05e84e6SDmitry Torokhov type->process_pkt = usbtouch_process_pkt; 1568d05e84e6SDmitry Torokhov 1569997ea58eSDaniel Mack usbtouch->data = usb_alloc_coherent(udev, type->rept_size, 1570d05e84e6SDmitry Torokhov GFP_KERNEL, &usbtouch->data_dma); 1571d05e84e6SDmitry Torokhov if (!usbtouch->data) 1572d05e84e6SDmitry Torokhov goto out_free; 1573d05e84e6SDmitry Torokhov 157462aa366dSDaniel Ritz if (type->get_pkt_len) { 1575d05e84e6SDmitry Torokhov usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 1576d05e84e6SDmitry Torokhov if (!usbtouch->buffer) 1577d05e84e6SDmitry Torokhov goto out_free_buffers; 1578d05e84e6SDmitry Torokhov } 1579d05e84e6SDmitry Torokhov 1580d05e84e6SDmitry Torokhov usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 1581d05e84e6SDmitry Torokhov if (!usbtouch->irq) { 1582b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1583b741ab9dSGreg Kroah-Hartman "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__); 1584d05e84e6SDmitry Torokhov goto out_free_buffers; 1585d05e84e6SDmitry Torokhov } 1586d05e84e6SDmitry Torokhov 1587fea4d14bSOndrej Zary usbtouch->interface = intf; 1588d05e84e6SDmitry Torokhov usbtouch->input = input_dev; 1589d05e84e6SDmitry Torokhov 1590d05e84e6SDmitry Torokhov if (udev->manufacturer) 1591d05e84e6SDmitry Torokhov strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 1592d05e84e6SDmitry Torokhov 1593d05e84e6SDmitry Torokhov if (udev->product) { 1594d05e84e6SDmitry Torokhov if (udev->manufacturer) 1595d05e84e6SDmitry Torokhov strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 1596d05e84e6SDmitry Torokhov strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 1597d05e84e6SDmitry Torokhov } 1598d05e84e6SDmitry Torokhov 1599d05e84e6SDmitry Torokhov if (!strlen(usbtouch->name)) 1600d05e84e6SDmitry Torokhov snprintf(usbtouch->name, sizeof(usbtouch->name), 1601d05e84e6SDmitry Torokhov "USB Touchscreen %04x:%04x", 1602d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idVendor), 1603d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idProduct)); 1604d05e84e6SDmitry Torokhov 1605d05e84e6SDmitry Torokhov usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 16067b6dff98SVladimir Shebordaev strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 1607d05e84e6SDmitry Torokhov 1608d05e84e6SDmitry Torokhov input_dev->name = usbtouch->name; 1609d05e84e6SDmitry Torokhov input_dev->phys = usbtouch->phys; 1610d05e84e6SDmitry Torokhov usb_to_input_id(udev, &input_dev->id); 1611d05e84e6SDmitry Torokhov input_dev->dev.parent = &intf->dev; 1612d05e84e6SDmitry Torokhov 1613d05e84e6SDmitry Torokhov input_set_drvdata(input_dev, usbtouch); 1614d05e84e6SDmitry Torokhov 1615d05e84e6SDmitry Torokhov input_dev->open = usbtouch_open; 1616d05e84e6SDmitry Torokhov input_dev->close = usbtouch_close; 1617d05e84e6SDmitry Torokhov 16187b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 16197b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1620d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 1621d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 1622d05e84e6SDmitry Torokhov if (type->max_press) 1623d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 1624d05e84e6SDmitry Torokhov type->max_press, 0, 0); 1625d05e84e6SDmitry Torokhov 16265197424cSOndrej Zary if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) 1627fea4d14bSOndrej Zary usb_fill_int_urb(usbtouch->irq, udev, 1628fea4d14bSOndrej Zary usb_rcvintpipe(udev, endpoint->bEndpointAddress), 1629d05e84e6SDmitry Torokhov usbtouch->data, type->rept_size, 1630d05e84e6SDmitry Torokhov usbtouch_irq, usbtouch, endpoint->bInterval); 16315197424cSOndrej Zary else 16325197424cSOndrej Zary usb_fill_bulk_urb(usbtouch->irq, udev, 16335197424cSOndrej Zary usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), 16345197424cSOndrej Zary usbtouch->data, type->rept_size, 16355197424cSOndrej Zary usbtouch_irq, usbtouch); 1636d05e84e6SDmitry Torokhov 1637fea4d14bSOndrej Zary usbtouch->irq->dev = udev; 1638d05e84e6SDmitry Torokhov usbtouch->irq->transfer_dma = usbtouch->data_dma; 1639d05e84e6SDmitry Torokhov usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1640d05e84e6SDmitry Torokhov 1641a8aef622SOliver Neukum /* device specific allocations */ 1642a8aef622SOliver Neukum if (type->alloc) { 1643a8aef622SOliver Neukum err = type->alloc(usbtouch); 1644a8aef622SOliver Neukum if (err) { 1645b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1646b741ab9dSGreg Kroah-Hartman "%s - type->alloc() failed, err: %d\n", 1647b741ab9dSGreg Kroah-Hartman __func__, err); 1648a8aef622SOliver Neukum goto out_free_urb; 1649a8aef622SOliver Neukum } 1650a8aef622SOliver Neukum } 1651a8aef622SOliver Neukum 1652a8aef622SOliver Neukum /* device specific initialisation*/ 1653d05e84e6SDmitry Torokhov if (type->init) { 1654d05e84e6SDmitry Torokhov err = type->init(usbtouch); 1655d05e84e6SDmitry Torokhov if (err) { 1656b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1657b741ab9dSGreg Kroah-Hartman "%s - type->init() failed, err: %d\n", 1658b741ab9dSGreg Kroah-Hartman __func__, err); 1659a8aef622SOliver Neukum goto out_do_exit; 1660d05e84e6SDmitry Torokhov } 1661d05e84e6SDmitry Torokhov } 1662d05e84e6SDmitry Torokhov 1663d05e84e6SDmitry Torokhov err = input_register_device(usbtouch->input); 1664d05e84e6SDmitry Torokhov if (err) { 1665b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1666b741ab9dSGreg Kroah-Hartman "%s - input_register_device failed, err: %d\n", 1667b741ab9dSGreg Kroah-Hartman __func__, err); 16685197424cSOndrej Zary goto out_do_exit; 1669d05e84e6SDmitry Torokhov } 1670d05e84e6SDmitry Torokhov 1671d05e84e6SDmitry Torokhov usb_set_intfdata(intf, usbtouch); 1672d05e84e6SDmitry Torokhov 16731e87a430SOndrej Zary if (usbtouch->type->irq_always) { 16745d9efc59SOliver Neukum /* this can't fail */ 16755d9efc59SOliver Neukum usb_autopm_get_interface(intf); 16761e87a430SOndrej Zary err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); 16771e87a430SOndrej Zary if (err) { 16785d9efc59SOliver Neukum usb_autopm_put_interface(intf); 16790a5ebc88SGreg Kroah-Hartman dev_err(&intf->dev, 1680e27ad0feSGreg Kroah-Hartman "%s - usb_submit_urb failed with result: %d\n", 16811e87a430SOndrej Zary __func__, err); 16821e87a430SOndrej Zary goto out_unregister_input; 16831e87a430SOndrej Zary } 16841e87a430SOndrej Zary } 16852330ed18SDaniel Silverstone 1686d05e84e6SDmitry Torokhov return 0; 1687d05e84e6SDmitry Torokhov 16881e87a430SOndrej Zary out_unregister_input: 16891e87a430SOndrej Zary input_unregister_device(input_dev); 16901e87a430SOndrej Zary input_dev = NULL; 16915197424cSOndrej Zary out_do_exit: 16925197424cSOndrej Zary if (type->exit) 16935197424cSOndrej Zary type->exit(usbtouch); 16941e87a430SOndrej Zary out_free_urb: 16951e87a430SOndrej Zary usb_free_urb(usbtouch->irq); 1696d05e84e6SDmitry Torokhov out_free_buffers: 1697d05e84e6SDmitry Torokhov usbtouch_free_buffers(udev, usbtouch); 1698d05e84e6SDmitry Torokhov out_free: 1699d05e84e6SDmitry Torokhov input_free_device(input_dev); 1700d05e84e6SDmitry Torokhov kfree(usbtouch); 1701d05e84e6SDmitry Torokhov return err; 1702d05e84e6SDmitry Torokhov } 1703d05e84e6SDmitry Torokhov 1704d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf) 1705d05e84e6SDmitry Torokhov { 1706d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1707d05e84e6SDmitry Torokhov 1708d05e84e6SDmitry Torokhov if (!usbtouch) 1709d05e84e6SDmitry Torokhov return; 1710d05e84e6SDmitry Torokhov 17110a5ebc88SGreg Kroah-Hartman dev_dbg(&intf->dev, 1712b741ab9dSGreg Kroah-Hartman "%s - usbtouch is initialized, cleaning up\n", __func__); 1713b741ab9dSGreg Kroah-Hartman 1714d05e84e6SDmitry Torokhov usb_set_intfdata(intf, NULL); 1715722232bcSOliver Neukum /* this will stop IO via close */ 1716d05e84e6SDmitry Torokhov input_unregister_device(usbtouch->input); 1717d05e84e6SDmitry Torokhov usb_free_urb(usbtouch->irq); 17185197424cSOndrej Zary if (usbtouch->type->exit) 17195197424cSOndrej Zary usbtouch->type->exit(usbtouch); 1720d05e84e6SDmitry Torokhov usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 1721d05e84e6SDmitry Torokhov kfree(usbtouch); 1722d05e84e6SDmitry Torokhov } 1723d05e84e6SDmitry Torokhov 1724d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices); 1725d05e84e6SDmitry Torokhov 1726d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = { 1727d05e84e6SDmitry Torokhov .name = "usbtouchscreen", 1728d05e84e6SDmitry Torokhov .probe = usbtouch_probe, 1729d05e84e6SDmitry Torokhov .disconnect = usbtouch_disconnect, 1730ed4299e1SOliver Neukum .suspend = usbtouch_suspend, 1731ed4299e1SOliver Neukum .resume = usbtouch_resume, 1732a8aef622SOliver Neukum .reset_resume = usbtouch_reset_resume, 1733d05e84e6SDmitry Torokhov .id_table = usbtouch_devices, 17345d9efc59SOliver Neukum .supports_autosuspend = 1, 1735d05e84e6SDmitry Torokhov }; 1736d05e84e6SDmitry Torokhov 173708642e7cSGreg Kroah-Hartman module_usb_driver(usbtouch_driver); 1738d05e84e6SDmitry Torokhov 1739d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR); 1740d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC); 1741d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL"); 1742d05e84e6SDmitry Torokhov 1743d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb"); 1744d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch"); 1745d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb"); 1746