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 \ 149139ebe8dSDaniel Ritz | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ 150ec42d448SDaniel Ritz | USB_DEVICE_ID_MATCH_DEVICE, \ 151ec42d448SDaniel Ritz .idVendor = (vend), \ 152ec42d448SDaniel Ritz .idProduct = (prod), \ 153ec42d448SDaniel Ritz .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 154ec42d448SDaniel Ritz .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE 155ec42d448SDaniel Ritz 1569cb3ce52SMárton Németh static const struct usb_device_id usbtouch_devices[] = { 157c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 158ec42d448SDaniel Ritz /* ignore the HID capable devices, handled by usbhid */ 159ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 160ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 161ec42d448SDaniel Ritz 162ec42d448SDaniel Ritz /* normal device IDs */ 163d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 164d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 165d05e84e6SDmitry Torokhov {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 166d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 167d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 168d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 169d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 170d05e84e6SDmitry Torokhov #endif 171d05e84e6SDmitry Torokhov 172c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 173d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 174d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 175d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 176d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 177d05e84e6SDmitry Torokhov #endif 178d05e84e6SDmitry Torokhov 179c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 180d05e84e6SDmitry Torokhov {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 181d05e84e6SDmitry Torokhov #endif 182d05e84e6SDmitry Torokhov 183c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 184d05e84e6SDmitry Torokhov {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 18509910509SGlenn Sommer {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, 186d05e84e6SDmitry Torokhov #endif 187d05e84e6SDmitry Torokhov 188c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 189d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 190d05e84e6SDmitry Torokhov #endif 191d05e84e6SDmitry Torokhov 192c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 193d05e84e6SDmitry Torokhov {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 194d05e84e6SDmitry Torokhov #endif 195d05e84e6SDmitry Torokhov 196c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 197d05e84e6SDmitry Torokhov {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 198d05e84e6SDmitry Torokhov #endif 199d05e84e6SDmitry Torokhov 200df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 201df561fcdSOndrej Zary {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 202df561fcdSOndrej Zary {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 203df561fcdSOndrej Zary #endif 204df561fcdSOndrej Zary 205a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 206a14a8401SOndrej Zary {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 207a14a8401SOndrej Zary #endif 208a14a8401SOndrej Zary 2099d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 2109d5657dbSIlya Frolov {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 2119d5657dbSIlya Frolov #endif 2129d5657dbSIlya Frolov 21314e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 21414e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 21514e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 21614e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 21714e40206SJerrold Jones #endif 21814e40206SJerrold Jones 219f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 220f7370699SJim Persson {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, 221f7370699SJim Persson #endif 222f7370699SJim Persson 2239e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2249e3b2583SFlorian Echtler {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, 2259e3b2583SFlorian Echtler #endif 2262330ed18SDaniel Silverstone 2272330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 2282330ed18SDaniel Silverstone {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, 2292330ed18SDaniel Silverstone #endif 2302330ed18SDaniel Silverstone 23138771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 23238771bb4SPetr Štetiar /* TC5UH */ 23338771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, 23438771bb4SPetr Štetiar /* TC4UM */ 23538771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, 236dbe1420bSPetr Štetiar #endif 237dbe1420bSPetr Štetiar 2385197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 2395197424cSOndrej Zary /* data interface only */ 2405197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), 2415197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2425197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), 2435197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2445197424cSOndrej Zary #endif 2455197424cSOndrej Zary 246d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 247d2cc817aSMichael Gebetsroither {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, 248d2cc817aSMichael Gebetsroither #endif 249d2cc817aSMichael Gebetsroither 250aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 251aa87512fSArmando Visconti {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, 252aa87512fSArmando Visconti #endif 253aa87512fSArmando Visconti 254d05e84e6SDmitry Torokhov {} 255d05e84e6SDmitry Torokhov }; 256d05e84e6SDmitry Torokhov 257d05e84e6SDmitry Torokhov 258d05e84e6SDmitry Torokhov /***************************************************************************** 2599e3b2583SFlorian Echtler * e2i Part 2609e3b2583SFlorian Echtler */ 2619e3b2583SFlorian Echtler 2629e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2639e3b2583SFlorian Echtler static int e2i_init(struct usbtouch_usb *usbtouch) 2649e3b2583SFlorian Echtler { 2659e3b2583SFlorian Echtler int ret; 266fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 2679e3b2583SFlorian Echtler 268fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 2699e3b2583SFlorian Echtler 0x01, 0x02, 0x0000, 0x0081, 2709e3b2583SFlorian Echtler NULL, 0, USB_CTRL_SET_TIMEOUT); 2719e3b2583SFlorian Echtler 272*b741ab9dSGreg Kroah-Hartman dev_dbg(&usbtouch->input->dev, 273*b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n", 2749e3b2583SFlorian Echtler __func__, ret); 2759e3b2583SFlorian Echtler return ret; 2769e3b2583SFlorian Echtler } 2779e3b2583SFlorian Echtler 2789e3b2583SFlorian Echtler static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 2799e3b2583SFlorian Echtler { 2809e3b2583SFlorian Echtler int tmp = (pkt[0] << 8) | pkt[1]; 2819e3b2583SFlorian Echtler dev->x = (pkt[2] << 8) | pkt[3]; 2829e3b2583SFlorian Echtler dev->y = (pkt[4] << 8) | pkt[5]; 2839e3b2583SFlorian Echtler 2849e3b2583SFlorian Echtler tmp = tmp - 0xA000; 2859e3b2583SFlorian Echtler dev->touch = (tmp > 0); 2869e3b2583SFlorian Echtler dev->press = (tmp > 0 ? tmp : 0); 2879e3b2583SFlorian Echtler 2889e3b2583SFlorian Echtler return 1; 2899e3b2583SFlorian Echtler } 2909e3b2583SFlorian Echtler #endif 2919e3b2583SFlorian Echtler 2929e3b2583SFlorian Echtler 2939e3b2583SFlorian Echtler /***************************************************************************** 294d05e84e6SDmitry Torokhov * eGalax part 295d05e84e6SDmitry Torokhov */ 296d05e84e6SDmitry Torokhov 297c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 298d05e84e6SDmitry Torokhov 29962aa366dSDaniel Ritz #ifndef MULTI_PACKET 30062aa366dSDaniel Ritz #define MULTI_PACKET 30162aa366dSDaniel Ritz #endif 30262aa366dSDaniel Ritz 303d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK 0xFE 304d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT 0x80 305d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG 0x0A 306d05e84e6SDmitry Torokhov 307d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 308d05e84e6SDmitry Torokhov { 309d05e84e6SDmitry Torokhov if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 310d05e84e6SDmitry Torokhov return 0; 311d05e84e6SDmitry Torokhov 312d05e84e6SDmitry Torokhov dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 313d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 314d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 315d05e84e6SDmitry Torokhov 316d05e84e6SDmitry Torokhov return 1; 317d05e84e6SDmitry Torokhov } 318d05e84e6SDmitry Torokhov 319d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len) 320d05e84e6SDmitry Torokhov { 321d05e84e6SDmitry Torokhov switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 322d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_REPT: 323d05e84e6SDmitry Torokhov return 5; 324d05e84e6SDmitry Torokhov 325d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_DIAG: 326d05e84e6SDmitry Torokhov if (len < 2) 327d05e84e6SDmitry Torokhov return -1; 328d05e84e6SDmitry Torokhov 329d05e84e6SDmitry Torokhov return buf[1] + 2; 330d05e84e6SDmitry Torokhov } 331d05e84e6SDmitry Torokhov 332d05e84e6SDmitry Torokhov return 0; 333d05e84e6SDmitry Torokhov } 334d05e84e6SDmitry Torokhov #endif 335d05e84e6SDmitry Torokhov 336aa87512fSArmando Visconti /***************************************************************************** 337aa87512fSArmando Visconti * EasyTouch part 338aa87512fSArmando Visconti */ 339aa87512fSArmando Visconti 340aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 341aa87512fSArmando Visconti 342aa87512fSArmando Visconti #ifndef MULTI_PACKET 343aa87512fSArmando Visconti #define MULTI_PACKET 344aa87512fSArmando Visconti #endif 345aa87512fSArmando Visconti 346aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_MASK 0xFE 347aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT 0x80 348aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT2 0xB0 349aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_DIAG 0x0A 350aa87512fSArmando Visconti 351aa87512fSArmando Visconti static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 352aa87512fSArmando Visconti { 353aa87512fSArmando Visconti if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && 354aa87512fSArmando Visconti (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) 355aa87512fSArmando Visconti return 0; 356aa87512fSArmando Visconti 357aa87512fSArmando Visconti dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); 358aa87512fSArmando Visconti dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); 359aa87512fSArmando Visconti dev->touch = pkt[0] & 0x01; 360aa87512fSArmando Visconti 361aa87512fSArmando Visconti return 1; 362aa87512fSArmando Visconti } 363aa87512fSArmando Visconti 364aa87512fSArmando Visconti static int etouch_get_pkt_len(unsigned char *buf, int len) 365aa87512fSArmando Visconti { 366aa87512fSArmando Visconti switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { 367aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_REPT: 368aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_REPT2: 369aa87512fSArmando Visconti return 5; 370aa87512fSArmando Visconti 371aa87512fSArmando Visconti case ETOUCH_PKT_TYPE_DIAG: 372aa87512fSArmando Visconti if (len < 2) 373aa87512fSArmando Visconti return -1; 374aa87512fSArmando Visconti 375aa87512fSArmando Visconti return buf[1] + 2; 376aa87512fSArmando Visconti } 377aa87512fSArmando Visconti 378aa87512fSArmando Visconti return 0; 379aa87512fSArmando Visconti } 380aa87512fSArmando Visconti #endif 381d05e84e6SDmitry Torokhov 382d05e84e6SDmitry Torokhov /***************************************************************************** 383d05e84e6SDmitry Torokhov * PanJit Part 384d05e84e6SDmitry Torokhov */ 385c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 386d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 387d05e84e6SDmitry Torokhov { 388d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 389d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 390d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 391d05e84e6SDmitry Torokhov 392d05e84e6SDmitry Torokhov return 1; 393d05e84e6SDmitry Torokhov } 394d05e84e6SDmitry Torokhov #endif 395d05e84e6SDmitry Torokhov 396d05e84e6SDmitry Torokhov 397d05e84e6SDmitry Torokhov /***************************************************************************** 398d05e84e6SDmitry Torokhov * 3M/Microtouch Part 399d05e84e6SDmitry Torokhov */ 400c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 401d05e84e6SDmitry Torokhov 402d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT 1 403d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET 7 404d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID 10 405d05e84e6SDmitry Torokhov 406d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 407d05e84e6SDmitry Torokhov { 408c9cbf3d3SDan Streetman if (hwcalib_xy) { 409c9cbf3d3SDan Streetman dev->x = (pkt[4] << 8) | pkt[3]; 410c9cbf3d3SDan Streetman dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 411c9cbf3d3SDan Streetman } else { 412d05e84e6SDmitry Torokhov dev->x = (pkt[8] << 8) | pkt[7]; 413d05e84e6SDmitry Torokhov dev->y = (pkt[10] << 8) | pkt[9]; 414c9cbf3d3SDan Streetman } 415d05e84e6SDmitry Torokhov dev->touch = (pkt[2] & 0x40) ? 1 : 0; 416d05e84e6SDmitry Torokhov 417d05e84e6SDmitry Torokhov return 1; 418d05e84e6SDmitry Torokhov } 419d05e84e6SDmitry Torokhov 420d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch) 421d05e84e6SDmitry Torokhov { 422d05e84e6SDmitry Torokhov int ret, i; 423fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 424d05e84e6SDmitry Torokhov 425fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 426d05e84e6SDmitry Torokhov MTOUCHUSB_RESET, 427d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 428d05e84e6SDmitry Torokhov 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 429*b741ab9dSGreg Kroah-Hartman dev_dbg(&usbtouch->input->dev, 430*b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n", 431ea3e6c59SHarvey Harrison __func__, ret); 432d05e84e6SDmitry Torokhov if (ret < 0) 433d05e84e6SDmitry Torokhov return ret; 434d05e84e6SDmitry Torokhov msleep(150); 435d05e84e6SDmitry Torokhov 436d05e84e6SDmitry Torokhov for (i = 0; i < 3; i++) { 437fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 438d05e84e6SDmitry Torokhov MTOUCHUSB_ASYNC_REPORT, 439d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 440d05e84e6SDmitry Torokhov 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 441*b741ab9dSGreg Kroah-Hartman dev_dbg(&usbtouch->input->dev, 442*b741ab9dSGreg Kroah-Hartman "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n", 443ea3e6c59SHarvey Harrison __func__, ret); 444d05e84e6SDmitry Torokhov if (ret >= 0) 445d05e84e6SDmitry Torokhov break; 446d05e84e6SDmitry Torokhov if (ret != -EPIPE) 447d05e84e6SDmitry Torokhov return ret; 448d05e84e6SDmitry Torokhov } 449d05e84e6SDmitry Torokhov 450c9cbf3d3SDan Streetman /* Default min/max xy are the raw values, override if using hw-calib */ 451c9cbf3d3SDan Streetman if (hwcalib_xy) { 452c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 453c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 454c9cbf3d3SDan Streetman } 455c9cbf3d3SDan Streetman 456d05e84e6SDmitry Torokhov return 0; 457d05e84e6SDmitry Torokhov } 458d05e84e6SDmitry Torokhov #endif 459d05e84e6SDmitry Torokhov 460d05e84e6SDmitry Torokhov 461d05e84e6SDmitry Torokhov /***************************************************************************** 462d05e84e6SDmitry Torokhov * ITM Part 463d05e84e6SDmitry Torokhov */ 464c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 465d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 466d05e84e6SDmitry Torokhov { 467d05e84e6SDmitry Torokhov int touch; 468d05e84e6SDmitry Torokhov /* 469d05e84e6SDmitry Torokhov * ITM devices report invalid x/y data if not touched. 470d05e84e6SDmitry Torokhov * if the screen was touched before but is not touched any more 471d05e84e6SDmitry Torokhov * report touch as 0 with the last valid x/y data once. then stop 472d05e84e6SDmitry Torokhov * reporting data until touched again. 473d05e84e6SDmitry Torokhov */ 474d05e84e6SDmitry Torokhov dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 475d05e84e6SDmitry Torokhov 476d05e84e6SDmitry Torokhov touch = ~pkt[7] & 0x20; 477d05e84e6SDmitry Torokhov if (!touch) { 478d05e84e6SDmitry Torokhov if (dev->touch) { 479d05e84e6SDmitry Torokhov dev->touch = 0; 480d05e84e6SDmitry Torokhov return 1; 481d05e84e6SDmitry Torokhov } 482d05e84e6SDmitry Torokhov 483d05e84e6SDmitry Torokhov return 0; 484d05e84e6SDmitry Torokhov } 485d05e84e6SDmitry Torokhov 486d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 487d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 488d05e84e6SDmitry Torokhov dev->touch = touch; 489d05e84e6SDmitry Torokhov 490d05e84e6SDmitry Torokhov return 1; 491d05e84e6SDmitry Torokhov } 492d05e84e6SDmitry Torokhov #endif 493d05e84e6SDmitry Torokhov 494d05e84e6SDmitry Torokhov 495d05e84e6SDmitry Torokhov /***************************************************************************** 496d05e84e6SDmitry Torokhov * eTurboTouch part 497d05e84e6SDmitry Torokhov */ 498c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 49962aa366dSDaniel Ritz #ifndef MULTI_PACKET 50062aa366dSDaniel Ritz #define MULTI_PACKET 50162aa366dSDaniel Ritz #endif 502d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 503d05e84e6SDmitry Torokhov { 504d05e84e6SDmitry Torokhov unsigned int shift; 505d05e84e6SDmitry Torokhov 506d05e84e6SDmitry Torokhov /* packets should start with sync */ 507d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80)) 508d05e84e6SDmitry Torokhov return 0; 509d05e84e6SDmitry Torokhov 510d05e84e6SDmitry Torokhov shift = (6 - (pkt[0] & 0x03)); 511d05e84e6SDmitry Torokhov dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 512d05e84e6SDmitry Torokhov dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 513d05e84e6SDmitry Torokhov dev->touch = (pkt[0] & 0x10) ? 1 : 0; 514d05e84e6SDmitry Torokhov 515d05e84e6SDmitry Torokhov return 1; 516d05e84e6SDmitry Torokhov } 517d05e84e6SDmitry Torokhov 518d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len) 519d05e84e6SDmitry Torokhov { 520d05e84e6SDmitry Torokhov if (buf[0] & 0x80) 521d05e84e6SDmitry Torokhov return 5; 522d05e84e6SDmitry Torokhov if (buf[0] == 0x01) 523d05e84e6SDmitry Torokhov return 3; 524d05e84e6SDmitry Torokhov return 0; 525d05e84e6SDmitry Torokhov } 526d05e84e6SDmitry Torokhov #endif 527d05e84e6SDmitry Torokhov 528d05e84e6SDmitry Torokhov 529d05e84e6SDmitry Torokhov /***************************************************************************** 530d05e84e6SDmitry Torokhov * Gunze part 531d05e84e6SDmitry Torokhov */ 532c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 533d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 534d05e84e6SDmitry Torokhov { 535d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 536d05e84e6SDmitry Torokhov return 0; 537d05e84e6SDmitry Torokhov 538d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 539d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 540d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x20; 541d05e84e6SDmitry Torokhov 542d05e84e6SDmitry Torokhov return 1; 543d05e84e6SDmitry Torokhov } 544d05e84e6SDmitry Torokhov #endif 545d05e84e6SDmitry Torokhov 546d05e84e6SDmitry Torokhov /***************************************************************************** 547d05e84e6SDmitry Torokhov * DMC TSC-10/25 Part 548d05e84e6SDmitry Torokhov * 549d05e84e6SDmitry Torokhov * Documentation about the controller and it's protocol can be found at 550d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 551d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 552d05e84e6SDmitry Torokhov */ 553c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 554d05e84e6SDmitry Torokhov 555d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */ 556d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT 0x50 557d05e84e6SDmitry Torokhov #define TSC10_RATE_30 0x40 558d05e84e6SDmitry Torokhov #define TSC10_RATE_50 0x41 559d05e84e6SDmitry Torokhov #define TSC10_RATE_80 0x42 560d05e84e6SDmitry Torokhov #define TSC10_RATE_100 0x43 561d05e84e6SDmitry Torokhov #define TSC10_RATE_130 0x44 562d05e84e6SDmitry Torokhov #define TSC10_RATE_150 0x45 563d05e84e6SDmitry Torokhov 564d05e84e6SDmitry Torokhov /* commands */ 565d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET 0x55 566d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE 0x05 567d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1 0x01 568d05e84e6SDmitry Torokhov 569d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 570d05e84e6SDmitry Torokhov { 571fea4d14bSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 57276d057ceSOliver Neukum int ret = -ENOMEM; 57376d057ceSOliver Neukum unsigned char *buf; 574d05e84e6SDmitry Torokhov 575a8aef622SOliver Neukum buf = kmalloc(2, GFP_NOIO); 57676d057ceSOliver Neukum if (!buf) 57776d057ceSOliver Neukum goto err_nobuf; 578d05e84e6SDmitry Torokhov /* reset */ 579d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 580d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 581d05e84e6SDmitry Torokhov TSC10_CMD_RESET, 582d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 583d05e84e6SDmitry Torokhov 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 584d05e84e6SDmitry Torokhov if (ret < 0) 58576d057ceSOliver Neukum goto err_out; 5862ec6f246SNuno Lucas if (buf[0] != 0x06) { 58776d057ceSOliver Neukum ret = -ENODEV; 58876d057ceSOliver Neukum goto err_out; 58976d057ceSOliver Neukum } 590d05e84e6SDmitry Torokhov 591d05e84e6SDmitry Torokhov /* set coordinate output rate */ 592d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 593d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 594d05e84e6SDmitry Torokhov TSC10_CMD_RATE, 595d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 596d05e84e6SDmitry Torokhov TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 597d05e84e6SDmitry Torokhov if (ret < 0) 59876d057ceSOliver Neukum goto err_out; 5992ec6f246SNuno Lucas if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 60076d057ceSOliver Neukum ret = -ENODEV; 60176d057ceSOliver Neukum goto err_out; 60276d057ceSOliver Neukum } 603d05e84e6SDmitry Torokhov 604d05e84e6SDmitry Torokhov /* start sending data */ 605d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 606d05e84e6SDmitry Torokhov TSC10_CMD_DATA1, 607d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 608d05e84e6SDmitry Torokhov 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 60976d057ceSOliver Neukum err_out: 61076d057ceSOliver Neukum kfree(buf); 61176d057ceSOliver Neukum err_nobuf: 612d05e84e6SDmitry Torokhov return ret; 613d05e84e6SDmitry Torokhov } 614d05e84e6SDmitry Torokhov 615d05e84e6SDmitry Torokhov 616d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 617d05e84e6SDmitry Torokhov { 618d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 619d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 620d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 621d05e84e6SDmitry Torokhov 622d05e84e6SDmitry Torokhov return 1; 623d05e84e6SDmitry Torokhov } 624d05e84e6SDmitry Torokhov #endif 625d05e84e6SDmitry Torokhov 626d05e84e6SDmitry Torokhov 627d05e84e6SDmitry Torokhov /***************************************************************************** 628df561fcdSOndrej Zary * IRTOUCH Part 629df561fcdSOndrej Zary */ 630df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 631df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 632df561fcdSOndrej Zary { 633df561fcdSOndrej Zary dev->x = (pkt[3] << 8) | pkt[2]; 634df561fcdSOndrej Zary dev->y = (pkt[5] << 8) | pkt[4]; 635df561fcdSOndrej Zary dev->touch = (pkt[1] & 0x03) ? 1 : 0; 636df561fcdSOndrej Zary 637df561fcdSOndrej Zary return 1; 638df561fcdSOndrej Zary } 639df561fcdSOndrej Zary #endif 640df561fcdSOndrej Zary 641dbe1420bSPetr Štetiar /***************************************************************************** 64238771bb4SPetr Štetiar * ET&T TC5UH/TC4UM part 643dbe1420bSPetr Štetiar */ 64438771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 64538771bb4SPetr Štetiar static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 646dbe1420bSPetr Štetiar { 647dbe1420bSPetr Štetiar dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 648dbe1420bSPetr Štetiar dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 649dbe1420bSPetr Štetiar dev->touch = pkt[0] & 0x01; 650dbe1420bSPetr Štetiar 651dbe1420bSPetr Štetiar return 1; 652dbe1420bSPetr Štetiar } 653dbe1420bSPetr Štetiar #endif 654df561fcdSOndrej Zary 655df561fcdSOndrej Zary /***************************************************************************** 656a14a8401SOndrej Zary * IdealTEK URTC1000 Part 657a14a8401SOndrej Zary */ 658a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 65962aa366dSDaniel Ritz #ifndef MULTI_PACKET 66062aa366dSDaniel Ritz #define MULTI_PACKET 66162aa366dSDaniel Ritz #endif 662a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len) 663a14a8401SOndrej Zary { 664a14a8401SOndrej Zary if (buf[0] & 0x80) 665a14a8401SOndrej Zary return 5; 666a14a8401SOndrej Zary if (buf[0] == 0x01) 667a14a8401SOndrej Zary return len; 668a14a8401SOndrej Zary return 0; 669a14a8401SOndrej Zary } 670a14a8401SOndrej Zary 671a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 672a14a8401SOndrej Zary { 673a14a8401SOndrej Zary switch (pkt[0] & 0x98) { 674a14a8401SOndrej Zary case 0x88: 675a14a8401SOndrej Zary /* touch data in IdealTEK mode */ 676a14a8401SOndrej Zary dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 677a14a8401SOndrej Zary dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 678a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 679a14a8401SOndrej Zary return 1; 680a14a8401SOndrej Zary 681a14a8401SOndrej Zary case 0x98: 682a14a8401SOndrej Zary /* touch data in MT emulation mode */ 683a14a8401SOndrej Zary dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 684a14a8401SOndrej Zary dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 685a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 686a14a8401SOndrej Zary return 1; 687a14a8401SOndrej Zary 688a14a8401SOndrej Zary default: 689a14a8401SOndrej Zary return 0; 690a14a8401SOndrej Zary } 691a14a8401SOndrej Zary } 692a14a8401SOndrej Zary #endif 693a14a8401SOndrej Zary 6949d5657dbSIlya Frolov /***************************************************************************** 6959d5657dbSIlya Frolov * General Touch Part 6969d5657dbSIlya Frolov */ 6979d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 6989d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 6999d5657dbSIlya Frolov { 700eb083ba2SRoy Yin dev->x = (pkt[2] << 8) | pkt[1]; 701eb083ba2SRoy Yin dev->y = (pkt[4] << 8) | pkt[3]; 7029d5657dbSIlya Frolov dev->press = pkt[5] & 0xff; 7039d5657dbSIlya Frolov dev->touch = pkt[0] & 0x01; 7049d5657dbSIlya Frolov 7059d5657dbSIlya Frolov return 1; 7069d5657dbSIlya Frolov } 7079d5657dbSIlya Frolov #endif 708a14a8401SOndrej Zary 709a14a8401SOndrej Zary /***************************************************************************** 71014e40206SJerrold Jones * GoTop Part 71114e40206SJerrold Jones */ 71214e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 71314e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 71414e40206SJerrold Jones { 71514e40206SJerrold Jones dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 71614e40206SJerrold Jones dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 71714e40206SJerrold Jones dev->touch = pkt[0] & 0x01; 718f7370699SJim Persson 719f7370699SJim Persson return 1; 720f7370699SJim Persson } 721f7370699SJim Persson #endif 722f7370699SJim Persson 723f7370699SJim Persson /***************************************************************************** 724f7370699SJim Persson * JASTEC Part 725f7370699SJim Persson */ 726f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 727f7370699SJim Persson static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 728f7370699SJim Persson { 729f7370699SJim Persson dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); 730f7370699SJim Persson dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); 731f7370699SJim Persson dev->touch = (pkt[0] & 0x40) >> 6; 732f7370699SJim Persson 73314e40206SJerrold Jones return 1; 73414e40206SJerrold Jones } 73514e40206SJerrold Jones #endif 73614e40206SJerrold Jones 7372330ed18SDaniel Silverstone /***************************************************************************** 7382330ed18SDaniel Silverstone * Zytronic Part 7392330ed18SDaniel Silverstone */ 7402330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 7412330ed18SDaniel Silverstone static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7422330ed18SDaniel Silverstone { 743*b741ab9dSGreg Kroah-Hartman struct input_dev *input = dev->input; 744*b741ab9dSGreg Kroah-Hartman 7452330ed18SDaniel Silverstone switch (pkt[0]) { 7462330ed18SDaniel Silverstone case 0x3A: /* command response */ 747*b741ab9dSGreg Kroah-Hartman dev_dbg(&input->dev, "%s: Command response %d\n", __func__, pkt[1]); 7482330ed18SDaniel Silverstone break; 7492330ed18SDaniel Silverstone 7502330ed18SDaniel Silverstone case 0xC0: /* down */ 7512330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 7522330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 7532330ed18SDaniel Silverstone dev->touch = 1; 754*b741ab9dSGreg Kroah-Hartman dev_dbg(&input->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y); 7552330ed18SDaniel Silverstone return 1; 7562330ed18SDaniel Silverstone 7572330ed18SDaniel Silverstone case 0x80: /* up */ 7582330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 7592330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 7602330ed18SDaniel Silverstone dev->touch = 0; 761*b741ab9dSGreg Kroah-Hartman dev_dbg(&input->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y); 7622330ed18SDaniel Silverstone return 1; 7632330ed18SDaniel Silverstone 7642330ed18SDaniel Silverstone default: 765*b741ab9dSGreg Kroah-Hartman dev_dbg(&input->dev, "%s: Unknown return %d\n", __func__, pkt[0]); 7662330ed18SDaniel Silverstone break; 7672330ed18SDaniel Silverstone } 7682330ed18SDaniel Silverstone 7692330ed18SDaniel Silverstone return 0; 7702330ed18SDaniel Silverstone } 7712330ed18SDaniel Silverstone #endif 77214e40206SJerrold Jones 77314e40206SJerrold Jones /***************************************************************************** 7745197424cSOndrej Zary * NEXIO Part 7755197424cSOndrej Zary */ 7765197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 7775197424cSOndrej Zary 7785197424cSOndrej Zary #define NEXIO_TIMEOUT 5000 7795197424cSOndrej Zary #define NEXIO_BUFSIZE 1024 7805197424cSOndrej Zary #define NEXIO_THRESHOLD 50 7815197424cSOndrej Zary 7825197424cSOndrej Zary struct nexio_priv { 7835197424cSOndrej Zary struct urb *ack; 7845197424cSOndrej Zary unsigned char *ack_buf; 7855197424cSOndrej Zary }; 7865197424cSOndrej Zary 7875197424cSOndrej Zary struct nexio_touch_packet { 7885197424cSOndrej Zary u8 flags; /* 0xe1 = touch, 0xe1 = release */ 7895197424cSOndrej Zary __be16 data_len; /* total bytes of touch data */ 7905197424cSOndrej Zary __be16 x_len; /* bytes for X axis */ 7915197424cSOndrej Zary __be16 y_len; /* bytes for Y axis */ 7925197424cSOndrej Zary u8 data[]; 7935197424cSOndrej Zary } __attribute__ ((packed)); 7945197424cSOndrej Zary 7955197424cSOndrej Zary static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; 7965197424cSOndrej Zary static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; 7975197424cSOndrej Zary 7985197424cSOndrej Zary static void nexio_ack_complete(struct urb *urb) 7995197424cSOndrej Zary { 8005197424cSOndrej Zary } 8015197424cSOndrej Zary 802a8aef622SOliver Neukum static int nexio_alloc(struct usbtouch_usb *usbtouch) 803a8aef622SOliver Neukum { 804a8aef622SOliver Neukum struct nexio_priv *priv; 805a8aef622SOliver Neukum int ret = -ENOMEM; 806a8aef622SOliver Neukum 807a8aef622SOliver Neukum usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); 808a8aef622SOliver Neukum if (!usbtouch->priv) 809a8aef622SOliver Neukum goto out_buf; 810a8aef622SOliver Neukum 811a8aef622SOliver Neukum priv = usbtouch->priv; 812a8aef622SOliver Neukum 813a8aef622SOliver Neukum priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), 814a8aef622SOliver Neukum GFP_KERNEL); 815a8aef622SOliver Neukum if (!priv->ack_buf) 816a8aef622SOliver Neukum goto err_priv; 817a8aef622SOliver Neukum 818a8aef622SOliver Neukum priv->ack = usb_alloc_urb(0, GFP_KERNEL); 819a8aef622SOliver Neukum if (!priv->ack) { 820*b741ab9dSGreg Kroah-Hartman dev_dbg(&usbtouch->input->dev, 821*b741ab9dSGreg Kroah-Hartman "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__); 822a8aef622SOliver Neukum goto err_ack_buf; 823a8aef622SOliver Neukum } 824a8aef622SOliver Neukum 825a8aef622SOliver Neukum return 0; 826a8aef622SOliver Neukum 827a8aef622SOliver Neukum err_ack_buf: 828a8aef622SOliver Neukum kfree(priv->ack_buf); 829a8aef622SOliver Neukum err_priv: 830a8aef622SOliver Neukum kfree(priv); 831a8aef622SOliver Neukum out_buf: 832a8aef622SOliver Neukum return ret; 833a8aef622SOliver Neukum } 834a8aef622SOliver Neukum 8355197424cSOndrej Zary static int nexio_init(struct usbtouch_usb *usbtouch) 8365197424cSOndrej Zary { 8375197424cSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 8385197424cSOndrej Zary struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; 839a8aef622SOliver Neukum struct nexio_priv *priv = usbtouch->priv; 8405197424cSOndrej Zary int ret = -ENOMEM; 8415197424cSOndrej Zary int actual_len, i; 8425197424cSOndrej Zary unsigned char *buf; 8435197424cSOndrej Zary char *firmware_ver = NULL, *device_name = NULL; 8445197424cSOndrej Zary int input_ep = 0, output_ep = 0; 8455197424cSOndrej Zary 8465197424cSOndrej Zary /* find first input and output endpoint */ 8475197424cSOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) { 8485197424cSOndrej Zary if (!input_ep && 8495197424cSOndrej Zary usb_endpoint_dir_in(&interface->endpoint[i].desc)) 8505197424cSOndrej Zary input_ep = interface->endpoint[i].desc.bEndpointAddress; 8515197424cSOndrej Zary if (!output_ep && 8525197424cSOndrej Zary usb_endpoint_dir_out(&interface->endpoint[i].desc)) 8535197424cSOndrej Zary output_ep = interface->endpoint[i].desc.bEndpointAddress; 8545197424cSOndrej Zary } 8555197424cSOndrej Zary if (!input_ep || !output_ep) 8565197424cSOndrej Zary return -ENXIO; 8575197424cSOndrej Zary 858a8aef622SOliver Neukum buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); 8595197424cSOndrej Zary if (!buf) 8605197424cSOndrej Zary goto out_buf; 8615197424cSOndrej Zary 8625197424cSOndrej Zary /* two empty reads */ 8635197424cSOndrej Zary for (i = 0; i < 2; i++) { 8645197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 8655197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 8665197424cSOndrej Zary NEXIO_TIMEOUT); 8675197424cSOndrej Zary if (ret < 0) 8685197424cSOndrej Zary goto out_buf; 8695197424cSOndrej Zary } 8705197424cSOndrej Zary 8715197424cSOndrej Zary /* send init command */ 8725197424cSOndrej Zary memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); 8735197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), 8745197424cSOndrej Zary buf, sizeof(nexio_init_pkt), &actual_len, 8755197424cSOndrej Zary NEXIO_TIMEOUT); 8765197424cSOndrej Zary if (ret < 0) 8775197424cSOndrej Zary goto out_buf; 8785197424cSOndrej Zary 8795197424cSOndrej Zary /* read replies */ 8805197424cSOndrej Zary for (i = 0; i < 3; i++) { 8815197424cSOndrej Zary memset(buf, 0, NEXIO_BUFSIZE); 8825197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 8835197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 8845197424cSOndrej Zary NEXIO_TIMEOUT); 8855197424cSOndrej Zary if (ret < 0 || actual_len < 1 || buf[1] != actual_len) 8865197424cSOndrej Zary continue; 8875197424cSOndrej Zary switch (buf[0]) { 8885197424cSOndrej Zary case 0x83: /* firmware version */ 8895197424cSOndrej Zary if (!firmware_ver) 890a8aef622SOliver Neukum firmware_ver = kstrdup(&buf[2], GFP_NOIO); 8915197424cSOndrej Zary break; 8925197424cSOndrej Zary case 0x84: /* device name */ 8935197424cSOndrej Zary if (!device_name) 894a8aef622SOliver Neukum device_name = kstrdup(&buf[2], GFP_NOIO); 8955197424cSOndrej Zary break; 8965197424cSOndrej Zary } 8975197424cSOndrej Zary } 8985197424cSOndrej Zary 8995197424cSOndrej Zary printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", 9005197424cSOndrej Zary device_name, firmware_ver); 9015197424cSOndrej Zary 9025197424cSOndrej Zary kfree(firmware_ver); 9035197424cSOndrej Zary kfree(device_name); 9045197424cSOndrej Zary 9055197424cSOndrej Zary usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), 9065197424cSOndrej Zary priv->ack_buf, sizeof(nexio_ack_pkt), 9075197424cSOndrej Zary nexio_ack_complete, usbtouch); 9085197424cSOndrej Zary ret = 0; 9095197424cSOndrej Zary 9105197424cSOndrej Zary out_buf: 9115197424cSOndrej Zary kfree(buf); 9125197424cSOndrej Zary return ret; 9135197424cSOndrej Zary } 9145197424cSOndrej Zary 9155197424cSOndrej Zary static void nexio_exit(struct usbtouch_usb *usbtouch) 9165197424cSOndrej Zary { 9175197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 9185197424cSOndrej Zary 9195197424cSOndrej Zary usb_kill_urb(priv->ack); 9205197424cSOndrej Zary usb_free_urb(priv->ack); 9215197424cSOndrej Zary kfree(priv->ack_buf); 9225197424cSOndrej Zary kfree(priv); 9235197424cSOndrej Zary } 9245197424cSOndrej Zary 9255197424cSOndrej Zary static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) 9265197424cSOndrej Zary { 9275197424cSOndrej Zary struct nexio_touch_packet *packet = (void *) pkt; 9285197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 9294aa5bbecSDmitry Torokhov unsigned int data_len = be16_to_cpu(packet->data_len); 9304aa5bbecSDmitry Torokhov unsigned int x_len = be16_to_cpu(packet->x_len); 9314aa5bbecSDmitry Torokhov unsigned int y_len = be16_to_cpu(packet->y_len); 9324aa5bbecSDmitry Torokhov int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; 9335197424cSOndrej Zary 9345197424cSOndrej Zary /* got touch data? */ 9355197424cSOndrej Zary if ((pkt[0] & 0xe0) != 0xe0) 9365197424cSOndrej Zary return 0; 9375197424cSOndrej Zary 9384aa5bbecSDmitry Torokhov if (data_len > 0xff) 9394aa5bbecSDmitry Torokhov data_len -= 0x100; 9404aa5bbecSDmitry Torokhov if (x_len > 0xff) 9414aa5bbecSDmitry Torokhov x_len -= 0x80; 942388bbcadSOndrej Zary 9435197424cSOndrej Zary /* send ACK */ 9445197424cSOndrej Zary ret = usb_submit_urb(priv->ack, GFP_ATOMIC); 9455197424cSOndrej Zary 9465197424cSOndrej Zary if (!usbtouch->type->max_xc) { 9474aa5bbecSDmitry Torokhov usbtouch->type->max_xc = 2 * x_len; 9484aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_X, 9494aa5bbecSDmitry Torokhov 0, usbtouch->type->max_xc, 0, 0); 9504aa5bbecSDmitry Torokhov usbtouch->type->max_yc = 2 * y_len; 9514aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_Y, 9524aa5bbecSDmitry Torokhov 0, usbtouch->type->max_yc, 0, 0); 9535197424cSOndrej Zary } 9545197424cSOndrej Zary /* 9555197424cSOndrej Zary * The device reports state of IR sensors on X and Y axes. 9565197424cSOndrej Zary * Each byte represents "darkness" percentage (0-100) of one element. 9575197424cSOndrej Zary * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. 9585197424cSOndrej Zary * This also means that there's a limited multi-touch capability but 9595197424cSOndrej Zary * it's disabled (and untested) here as there's no X driver for that. 9605197424cSOndrej Zary */ 9615197424cSOndrej Zary begin_x = end_x = begin_y = end_y = -1; 9624aa5bbecSDmitry Torokhov for (x = 0; x < x_len; x++) { 9635197424cSOndrej Zary if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { 9645197424cSOndrej Zary begin_x = x; 9655197424cSOndrej Zary continue; 9665197424cSOndrej Zary } 9675197424cSOndrej Zary if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { 9685197424cSOndrej Zary end_x = x - 1; 9694aa5bbecSDmitry Torokhov for (y = x_len; y < data_len; y++) { 9705197424cSOndrej Zary if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { 9714aa5bbecSDmitry Torokhov begin_y = y - x_len; 9725197424cSOndrej Zary continue; 9735197424cSOndrej Zary } 9745197424cSOndrej Zary if (end_y == -1 && 9755197424cSOndrej Zary begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { 9764aa5bbecSDmitry Torokhov end_y = y - 1 - x_len; 9775197424cSOndrej Zary w = end_x - begin_x; 9785197424cSOndrej Zary h = end_y - begin_y; 9795197424cSOndrej Zary #if 0 9805197424cSOndrej Zary /* multi-touch */ 9815197424cSOndrej Zary input_report_abs(usbtouch->input, 9825197424cSOndrej Zary ABS_MT_TOUCH_MAJOR, max(w,h)); 9835197424cSOndrej Zary input_report_abs(usbtouch->input, 9845197424cSOndrej Zary ABS_MT_TOUCH_MINOR, min(x,h)); 9855197424cSOndrej Zary input_report_abs(usbtouch->input, 9865197424cSOndrej Zary ABS_MT_POSITION_X, 2*begin_x+w); 9875197424cSOndrej Zary input_report_abs(usbtouch->input, 9885197424cSOndrej Zary ABS_MT_POSITION_Y, 2*begin_y+h); 9895197424cSOndrej Zary input_report_abs(usbtouch->input, 9905197424cSOndrej Zary ABS_MT_ORIENTATION, w > h); 9915197424cSOndrej Zary input_mt_sync(usbtouch->input); 9925197424cSOndrej Zary #endif 9935197424cSOndrej Zary /* single touch */ 9945197424cSOndrej Zary usbtouch->x = 2 * begin_x + w; 9955197424cSOndrej Zary usbtouch->y = 2 * begin_y + h; 9965197424cSOndrej Zary usbtouch->touch = packet->flags & 0x01; 9975197424cSOndrej Zary begin_y = end_y = -1; 9985197424cSOndrej Zary return 1; 9995197424cSOndrej Zary } 10005197424cSOndrej Zary } 10015197424cSOndrej Zary begin_x = end_x = -1; 10025197424cSOndrej Zary } 10035197424cSOndrej Zary 10045197424cSOndrej Zary } 10055197424cSOndrej Zary return 0; 10065197424cSOndrej Zary } 10075197424cSOndrej Zary #endif 10085197424cSOndrej Zary 10095197424cSOndrej Zary 10105197424cSOndrej Zary /***************************************************************************** 1011d2cc817aSMichael Gebetsroither * ELO part 1012d2cc817aSMichael Gebetsroither */ 1013d2cc817aSMichael Gebetsroither 1014d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 1015d2cc817aSMichael Gebetsroither 1016d2cc817aSMichael Gebetsroither static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 1017d2cc817aSMichael Gebetsroither { 1018d2cc817aSMichael Gebetsroither dev->x = (pkt[3] << 8) | pkt[2]; 1019d2cc817aSMichael Gebetsroither dev->y = (pkt[5] << 8) | pkt[4]; 1020d2cc817aSMichael Gebetsroither dev->touch = pkt[6] > 0; 1021d2cc817aSMichael Gebetsroither dev->press = pkt[6]; 1022d2cc817aSMichael Gebetsroither 1023d2cc817aSMichael Gebetsroither return 1; 1024d2cc817aSMichael Gebetsroither } 1025d2cc817aSMichael Gebetsroither #endif 1026d2cc817aSMichael Gebetsroither 1027d2cc817aSMichael Gebetsroither 1028d2cc817aSMichael Gebetsroither /***************************************************************************** 1029d05e84e6SDmitry Torokhov * the different device descriptors 1030d05e84e6SDmitry Torokhov */ 103162aa366dSDaniel Ritz #ifdef MULTI_PACKET 103262aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 103362aa366dSDaniel Ritz unsigned char *pkt, int len); 103462aa366dSDaniel Ritz #endif 103562aa366dSDaniel Ritz 1036d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = { 1037d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 1038d2cc817aSMichael Gebetsroither [DEVTYPE_ELO] = { 1039d2cc817aSMichael Gebetsroither .min_xc = 0x0, 1040d2cc817aSMichael Gebetsroither .max_xc = 0x0fff, 1041d2cc817aSMichael Gebetsroither .min_yc = 0x0, 1042d2cc817aSMichael Gebetsroither .max_yc = 0x0fff, 1043d2cc817aSMichael Gebetsroither .max_press = 0xff, 1044d2cc817aSMichael Gebetsroither .rept_size = 8, 1045d2cc817aSMichael Gebetsroither .read_data = elo_read_data, 1046d2cc817aSMichael Gebetsroither }, 1047d2cc817aSMichael Gebetsroither #endif 1048d2cc817aSMichael Gebetsroither 1049c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 1050d05e84e6SDmitry Torokhov [DEVTYPE_EGALAX] = { 1051d05e84e6SDmitry Torokhov .min_xc = 0x0, 1052d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 1053d05e84e6SDmitry Torokhov .min_yc = 0x0, 1054d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 1055d05e84e6SDmitry Torokhov .rept_size = 16, 1056d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1057d05e84e6SDmitry Torokhov .get_pkt_len = egalax_get_pkt_len, 1058d05e84e6SDmitry Torokhov .read_data = egalax_read_data, 1059d05e84e6SDmitry Torokhov }, 1060d05e84e6SDmitry Torokhov #endif 1061d05e84e6SDmitry Torokhov 1062c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 1063d05e84e6SDmitry Torokhov [DEVTYPE_PANJIT] = { 1064d05e84e6SDmitry Torokhov .min_xc = 0x0, 1065d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1066d05e84e6SDmitry Torokhov .min_yc = 0x0, 1067d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1068d05e84e6SDmitry Torokhov .rept_size = 8, 1069d05e84e6SDmitry Torokhov .read_data = panjit_read_data, 1070d05e84e6SDmitry Torokhov }, 1071d05e84e6SDmitry Torokhov #endif 1072d05e84e6SDmitry Torokhov 1073c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 1074d05e84e6SDmitry Torokhov [DEVTYPE_3M] = { 1075d05e84e6SDmitry Torokhov .min_xc = 0x0, 1076d05e84e6SDmitry Torokhov .max_xc = 0x4000, 1077d05e84e6SDmitry Torokhov .min_yc = 0x0, 1078d05e84e6SDmitry Torokhov .max_yc = 0x4000, 1079d05e84e6SDmitry Torokhov .rept_size = 11, 1080d05e84e6SDmitry Torokhov .read_data = mtouch_read_data, 1081d05e84e6SDmitry Torokhov .init = mtouch_init, 1082d05e84e6SDmitry Torokhov }, 1083d05e84e6SDmitry Torokhov #endif 1084d05e84e6SDmitry Torokhov 1085c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 1086d05e84e6SDmitry Torokhov [DEVTYPE_ITM] = { 1087d05e84e6SDmitry Torokhov .min_xc = 0x0, 1088d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1089d05e84e6SDmitry Torokhov .min_yc = 0x0, 1090d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1091d05e84e6SDmitry Torokhov .max_press = 0xff, 1092d05e84e6SDmitry Torokhov .rept_size = 8, 1093d05e84e6SDmitry Torokhov .read_data = itm_read_data, 1094d05e84e6SDmitry Torokhov }, 1095d05e84e6SDmitry Torokhov #endif 1096d05e84e6SDmitry Torokhov 1097c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 1098d05e84e6SDmitry Torokhov [DEVTYPE_ETURBO] = { 1099d05e84e6SDmitry Torokhov .min_xc = 0x0, 1100d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 1101d05e84e6SDmitry Torokhov .min_yc = 0x0, 1102d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 1103d05e84e6SDmitry Torokhov .rept_size = 8, 1104d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1105d05e84e6SDmitry Torokhov .get_pkt_len = eturbo_get_pkt_len, 1106d05e84e6SDmitry Torokhov .read_data = eturbo_read_data, 1107d05e84e6SDmitry Torokhov }, 1108d05e84e6SDmitry Torokhov #endif 1109d05e84e6SDmitry Torokhov 1110c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 1111d05e84e6SDmitry Torokhov [DEVTYPE_GUNZE] = { 1112d05e84e6SDmitry Torokhov .min_xc = 0x0, 1113d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1114d05e84e6SDmitry Torokhov .min_yc = 0x0, 1115d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1116d05e84e6SDmitry Torokhov .rept_size = 4, 1117d05e84e6SDmitry Torokhov .read_data = gunze_read_data, 1118d05e84e6SDmitry Torokhov }, 1119d05e84e6SDmitry Torokhov #endif 1120d05e84e6SDmitry Torokhov 1121c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 1122d05e84e6SDmitry Torokhov [DEVTYPE_DMC_TSC10] = { 1123d05e84e6SDmitry Torokhov .min_xc = 0x0, 1124d05e84e6SDmitry Torokhov .max_xc = 0x03ff, 1125d05e84e6SDmitry Torokhov .min_yc = 0x0, 1126d05e84e6SDmitry Torokhov .max_yc = 0x03ff, 1127d05e84e6SDmitry Torokhov .rept_size = 5, 1128d05e84e6SDmitry Torokhov .init = dmc_tsc10_init, 1129d05e84e6SDmitry Torokhov .read_data = dmc_tsc10_read_data, 1130d05e84e6SDmitry Torokhov }, 1131d05e84e6SDmitry Torokhov #endif 1132df561fcdSOndrej Zary 1133df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 1134df561fcdSOndrej Zary [DEVTYPE_IRTOUCH] = { 1135df561fcdSOndrej Zary .min_xc = 0x0, 1136df561fcdSOndrej Zary .max_xc = 0x0fff, 1137df561fcdSOndrej Zary .min_yc = 0x0, 1138df561fcdSOndrej Zary .max_yc = 0x0fff, 1139df561fcdSOndrej Zary .rept_size = 8, 1140df561fcdSOndrej Zary .read_data = irtouch_read_data, 1141df561fcdSOndrej Zary }, 1142df561fcdSOndrej Zary #endif 1143a14a8401SOndrej Zary 1144a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 1145a14a8401SOndrej Zary [DEVTYPE_IDEALTEK] = { 1146a14a8401SOndrej Zary .min_xc = 0x0, 1147a14a8401SOndrej Zary .max_xc = 0x0fff, 1148a14a8401SOndrej Zary .min_yc = 0x0, 1149a14a8401SOndrej Zary .max_yc = 0x0fff, 1150a14a8401SOndrej Zary .rept_size = 8, 1151a14a8401SOndrej Zary .process_pkt = usbtouch_process_multi, 1152a14a8401SOndrej Zary .get_pkt_len = idealtek_get_pkt_len, 1153a14a8401SOndrej Zary .read_data = idealtek_read_data, 1154a14a8401SOndrej Zary }, 1155a14a8401SOndrej Zary #endif 11569d5657dbSIlya Frolov 11579d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 11589d5657dbSIlya Frolov [DEVTYPE_GENERAL_TOUCH] = { 11599d5657dbSIlya Frolov .min_xc = 0x0, 1160eb083ba2SRoy Yin .max_xc = 0x7fff, 11619d5657dbSIlya Frolov .min_yc = 0x0, 1162eb083ba2SRoy Yin .max_yc = 0x7fff, 11639d5657dbSIlya Frolov .rept_size = 7, 11649d5657dbSIlya Frolov .read_data = general_touch_read_data, 116514e40206SJerrold Jones }, 11669d5657dbSIlya Frolov #endif 11679d5657dbSIlya Frolov 116814e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 116914e40206SJerrold Jones [DEVTYPE_GOTOP] = { 117014e40206SJerrold Jones .min_xc = 0x0, 117114e40206SJerrold Jones .max_xc = 0x03ff, 117214e40206SJerrold Jones .min_yc = 0x0, 117314e40206SJerrold Jones .max_yc = 0x03ff, 117414e40206SJerrold Jones .rept_size = 4, 117514e40206SJerrold Jones .read_data = gotop_read_data, 117614e40206SJerrold Jones }, 117714e40206SJerrold Jones #endif 1178f7370699SJim Persson 1179f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 1180f7370699SJim Persson [DEVTYPE_JASTEC] = { 1181f7370699SJim Persson .min_xc = 0x0, 1182f7370699SJim Persson .max_xc = 0x0fff, 1183f7370699SJim Persson .min_yc = 0x0, 1184f7370699SJim Persson .max_yc = 0x0fff, 1185f7370699SJim Persson .rept_size = 4, 1186f7370699SJim Persson .read_data = jastec_read_data, 1187f7370699SJim Persson }, 1188f7370699SJim Persson #endif 11899e3b2583SFlorian Echtler 11909e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 11919e3b2583SFlorian Echtler [DEVTYPE_E2I] = { 11929e3b2583SFlorian Echtler .min_xc = 0x0, 11939e3b2583SFlorian Echtler .max_xc = 0x7fff, 11949e3b2583SFlorian Echtler .min_yc = 0x0, 11959e3b2583SFlorian Echtler .max_yc = 0x7fff, 11969e3b2583SFlorian Echtler .rept_size = 6, 11979e3b2583SFlorian Echtler .init = e2i_init, 11989e3b2583SFlorian Echtler .read_data = e2i_read_data, 11999e3b2583SFlorian Echtler }, 12009e3b2583SFlorian Echtler #endif 12012330ed18SDaniel Silverstone 12022330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 12032330ed18SDaniel Silverstone [DEVTYPE_ZYTRONIC] = { 12042330ed18SDaniel Silverstone .min_xc = 0x0, 12052330ed18SDaniel Silverstone .max_xc = 0x03ff, 12062330ed18SDaniel Silverstone .min_yc = 0x0, 12072330ed18SDaniel Silverstone .max_yc = 0x03ff, 12082330ed18SDaniel Silverstone .rept_size = 5, 12092330ed18SDaniel Silverstone .read_data = zytronic_read_data, 12102330ed18SDaniel Silverstone .irq_always = true, 12112330ed18SDaniel Silverstone }, 12122330ed18SDaniel Silverstone #endif 1213dbe1420bSPetr Štetiar 121438771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 121538771bb4SPetr Štetiar [DEVTYPE_TC45USB] = { 1216dbe1420bSPetr Štetiar .min_xc = 0x0, 1217dbe1420bSPetr Štetiar .max_xc = 0x0fff, 1218dbe1420bSPetr Štetiar .min_yc = 0x0, 1219dbe1420bSPetr Štetiar .max_yc = 0x0fff, 1220dbe1420bSPetr Štetiar .rept_size = 5, 122138771bb4SPetr Štetiar .read_data = tc45usb_read_data, 1222dbe1420bSPetr Štetiar }, 1223dbe1420bSPetr Štetiar #endif 12245197424cSOndrej Zary 12255197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 12265197424cSOndrej Zary [DEVTYPE_NEXIO] = { 1227388bbcadSOndrej Zary .rept_size = 1024, 12285197424cSOndrej Zary .irq_always = true, 12295197424cSOndrej Zary .read_data = nexio_read_data, 1230a8aef622SOliver Neukum .alloc = nexio_alloc, 12315197424cSOndrej Zary .init = nexio_init, 12325197424cSOndrej Zary .exit = nexio_exit, 12335197424cSOndrej Zary }, 12345197424cSOndrej Zary #endif 1235aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 1236aa87512fSArmando Visconti [DEVTYPE_ETOUCH] = { 1237aa87512fSArmando Visconti .min_xc = 0x0, 1238aa87512fSArmando Visconti .max_xc = 0x07ff, 1239aa87512fSArmando Visconti .min_yc = 0x0, 1240aa87512fSArmando Visconti .max_yc = 0x07ff, 1241aa87512fSArmando Visconti .rept_size = 16, 1242aa87512fSArmando Visconti .process_pkt = usbtouch_process_multi, 1243aa87512fSArmando Visconti .get_pkt_len = etouch_get_pkt_len, 1244aa87512fSArmando Visconti .read_data = etouch_read_data, 1245aa87512fSArmando Visconti }, 1246aa87512fSArmando Visconti #endif 1247d05e84e6SDmitry Torokhov }; 1248d05e84e6SDmitry Torokhov 1249d05e84e6SDmitry Torokhov 1250d05e84e6SDmitry Torokhov /***************************************************************************** 1251d05e84e6SDmitry Torokhov * Generic Part 1252d05e84e6SDmitry Torokhov */ 1253d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 1254d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1255d05e84e6SDmitry Torokhov { 1256d05e84e6SDmitry Torokhov struct usbtouch_device_info *type = usbtouch->type; 1257d05e84e6SDmitry Torokhov 1258d05e84e6SDmitry Torokhov if (!type->read_data(usbtouch, pkt)) 1259d05e84e6SDmitry Torokhov return; 1260d05e84e6SDmitry Torokhov 1261d05e84e6SDmitry Torokhov input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 1262d05e84e6SDmitry Torokhov 1263d05e84e6SDmitry Torokhov if (swap_xy) { 1264d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 1265d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 1266d05e84e6SDmitry Torokhov } else { 1267d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 1268d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 1269d05e84e6SDmitry Torokhov } 1270d05e84e6SDmitry Torokhov if (type->max_press) 1271d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 1272d05e84e6SDmitry Torokhov input_sync(usbtouch->input); 1273d05e84e6SDmitry Torokhov } 1274d05e84e6SDmitry Torokhov 1275d05e84e6SDmitry Torokhov 1276d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET 1277d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 1278d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1279d05e84e6SDmitry Torokhov { 1280d05e84e6SDmitry Torokhov unsigned char *buffer; 1281d05e84e6SDmitry Torokhov int pkt_len, pos, buf_len, tmp; 1282d05e84e6SDmitry Torokhov 1283d05e84e6SDmitry Torokhov /* process buffer */ 1284d05e84e6SDmitry Torokhov if (unlikely(usbtouch->buf_len)) { 1285d05e84e6SDmitry Torokhov /* try to get size */ 1286d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1287d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1288d05e84e6SDmitry Torokhov 1289d05e84e6SDmitry Torokhov /* drop? */ 1290d05e84e6SDmitry Torokhov if (unlikely(!pkt_len)) 1291d05e84e6SDmitry Torokhov goto out_flush_buf; 1292d05e84e6SDmitry Torokhov 1293d05e84e6SDmitry Torokhov /* need to append -pkt_len bytes before able to get size */ 1294d05e84e6SDmitry Torokhov if (unlikely(pkt_len < 0)) { 1295d05e84e6SDmitry Torokhov int append = -pkt_len; 1296d05e84e6SDmitry Torokhov if (unlikely(append > len)) 1297d05e84e6SDmitry Torokhov append = len; 1298d05e84e6SDmitry Torokhov if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 1299d05e84e6SDmitry Torokhov goto out_flush_buf; 1300d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 1301d05e84e6SDmitry Torokhov usbtouch->buf_len += append; 1302d05e84e6SDmitry Torokhov 1303d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1304d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1305d05e84e6SDmitry Torokhov if (pkt_len < 0) 1306d05e84e6SDmitry Torokhov return; 1307d05e84e6SDmitry Torokhov } 1308d05e84e6SDmitry Torokhov 1309d05e84e6SDmitry Torokhov /* append */ 1310d05e84e6SDmitry Torokhov tmp = pkt_len - usbtouch->buf_len; 1311d05e84e6SDmitry Torokhov if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 1312d05e84e6SDmitry Torokhov goto out_flush_buf; 1313d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 1314d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 1315d05e84e6SDmitry Torokhov 1316d05e84e6SDmitry Torokhov buffer = pkt + tmp; 1317d05e84e6SDmitry Torokhov buf_len = len - tmp; 1318d05e84e6SDmitry Torokhov } else { 1319d05e84e6SDmitry Torokhov buffer = pkt; 1320d05e84e6SDmitry Torokhov buf_len = len; 1321d05e84e6SDmitry Torokhov } 1322d05e84e6SDmitry Torokhov 1323d05e84e6SDmitry Torokhov /* loop over the received packet, process */ 1324d05e84e6SDmitry Torokhov pos = 0; 1325d05e84e6SDmitry Torokhov while (pos < buf_len) { 1326d05e84e6SDmitry Torokhov /* get packet len */ 132762aa366dSDaniel Ritz pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 132862aa366dSDaniel Ritz buf_len - pos); 1329d05e84e6SDmitry Torokhov 133062aa366dSDaniel Ritz /* unknown packet: skip one byte */ 133162aa366dSDaniel Ritz if (unlikely(!pkt_len)) { 133262aa366dSDaniel Ritz pos++; 133362aa366dSDaniel Ritz continue; 133462aa366dSDaniel Ritz } 1335d05e84e6SDmitry Torokhov 1336d05e84e6SDmitry Torokhov /* full packet: process */ 1337d05e84e6SDmitry Torokhov if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 1338d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 1339d05e84e6SDmitry Torokhov } else { 1340d05e84e6SDmitry Torokhov /* incomplete packet: save in buffer */ 1341d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 1342d05e84e6SDmitry Torokhov usbtouch->buf_len = buf_len - pos; 1343d05e84e6SDmitry Torokhov return; 1344d05e84e6SDmitry Torokhov } 1345d05e84e6SDmitry Torokhov pos += pkt_len; 1346d05e84e6SDmitry Torokhov } 1347d05e84e6SDmitry Torokhov 1348d05e84e6SDmitry Torokhov out_flush_buf: 1349d05e84e6SDmitry Torokhov usbtouch->buf_len = 0; 1350d05e84e6SDmitry Torokhov return; 1351d05e84e6SDmitry Torokhov } 1352d05e84e6SDmitry Torokhov #endif 1353d05e84e6SDmitry Torokhov 1354d05e84e6SDmitry Torokhov 1355d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb) 1356d05e84e6SDmitry Torokhov { 1357d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = urb->context; 1358*b741ab9dSGreg Kroah-Hartman struct device *dev = &usbtouch->input->dev; 1359d05e84e6SDmitry Torokhov int retval; 1360d05e84e6SDmitry Torokhov 1361d05e84e6SDmitry Torokhov switch (urb->status) { 1362d05e84e6SDmitry Torokhov case 0: 1363d05e84e6SDmitry Torokhov /* success */ 1364d05e84e6SDmitry Torokhov break; 1365d05e84e6SDmitry Torokhov case -ETIME: 1366d05e84e6SDmitry Torokhov /* this urb is timing out */ 1367*b741ab9dSGreg Kroah-Hartman dev_dbg(dev, 1368*b741ab9dSGreg Kroah-Hartman "%s - urb timed out - was the device unplugged?\n", 1369ea3e6c59SHarvey Harrison __func__); 1370d05e84e6SDmitry Torokhov return; 1371d05e84e6SDmitry Torokhov case -ECONNRESET: 1372d05e84e6SDmitry Torokhov case -ENOENT: 1373d05e84e6SDmitry Torokhov case -ESHUTDOWN: 13745197424cSOndrej Zary case -EPIPE: 1375d05e84e6SDmitry Torokhov /* this urb is terminated, clean up */ 1376*b741ab9dSGreg Kroah-Hartman dev_dbg(dev, "%s - urb shutting down with status: %d\n", 1377ea3e6c59SHarvey Harrison __func__, urb->status); 1378d05e84e6SDmitry Torokhov return; 1379d05e84e6SDmitry Torokhov default: 1380*b741ab9dSGreg Kroah-Hartman dev_dbg(dev, "%s - nonzero urb status received: %d\n", 1381ea3e6c59SHarvey Harrison __func__, urb->status); 1382d05e84e6SDmitry Torokhov goto exit; 1383d05e84e6SDmitry Torokhov } 1384d05e84e6SDmitry Torokhov 1385d05e84e6SDmitry Torokhov usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 1386d05e84e6SDmitry Torokhov 1387d05e84e6SDmitry Torokhov exit: 13885d9efc59SOliver Neukum usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); 1389d05e84e6SDmitry Torokhov retval = usb_submit_urb(urb, GFP_ATOMIC); 1390d05e84e6SDmitry Torokhov if (retval) 1391f864b60aSGreg Kroah-Hartman dev_err(&usbtouch->input->dev, 1392e27ad0feSGreg Kroah-Hartman "%s - usb_submit_urb failed with result: %d\n", 1393ea3e6c59SHarvey Harrison __func__, retval); 1394d05e84e6SDmitry Torokhov } 1395d05e84e6SDmitry Torokhov 1396d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input) 1397d05e84e6SDmitry Torokhov { 1398d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 13995d9efc59SOliver Neukum int r; 1400d05e84e6SDmitry Torokhov 1401fea4d14bSOndrej Zary usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); 1402d05e84e6SDmitry Torokhov 14035d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; 14045d9efc59SOliver Neukum if (r < 0) 14055d9efc59SOliver Neukum goto out; 14065d9efc59SOliver Neukum 14072330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) { 14085d9efc59SOliver Neukum if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { 14095d9efc59SOliver Neukum r = -EIO; 14105d9efc59SOliver Neukum goto out_put; 14115d9efc59SOliver Neukum } 14122330ed18SDaniel Silverstone } 1413d05e84e6SDmitry Torokhov 14145d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 1; 14155d9efc59SOliver Neukum out_put: 14165d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 14175d9efc59SOliver Neukum out: 14185d9efc59SOliver Neukum return r; 1419d05e84e6SDmitry Torokhov } 1420d05e84e6SDmitry Torokhov 1421d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input) 1422d05e84e6SDmitry Torokhov { 1423d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 14245d9efc59SOliver Neukum int r; 1425d05e84e6SDmitry Torokhov 14262330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) 1427d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 14285d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface); 14295d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 0; 14305d9efc59SOliver Neukum if (!r) 14315d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 1432d05e84e6SDmitry Torokhov } 1433d05e84e6SDmitry Torokhov 1434ed4299e1SOliver Neukum static int usbtouch_suspend 1435ed4299e1SOliver Neukum (struct usb_interface *intf, pm_message_t message) 1436ed4299e1SOliver Neukum { 1437ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1438ed4299e1SOliver Neukum 1439ed4299e1SOliver Neukum usb_kill_urb(usbtouch->irq); 1440ed4299e1SOliver Neukum 1441ed4299e1SOliver Neukum return 0; 1442ed4299e1SOliver Neukum } 1443ed4299e1SOliver Neukum 1444ed4299e1SOliver Neukum static int usbtouch_resume(struct usb_interface *intf) 1445ed4299e1SOliver Neukum { 1446ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1447ed4299e1SOliver Neukum struct input_dev *input = usbtouch->input; 1448ed4299e1SOliver Neukum int result = 0; 1449ed4299e1SOliver Neukum 1450ed4299e1SOliver Neukum mutex_lock(&input->mutex); 1451ed4299e1SOliver Neukum if (input->users || usbtouch->type->irq_always) 1452ed4299e1SOliver Neukum result = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1453ed4299e1SOliver Neukum mutex_unlock(&input->mutex); 1454ed4299e1SOliver Neukum 1455ed4299e1SOliver Neukum return result; 1456ed4299e1SOliver Neukum } 1457d05e84e6SDmitry Torokhov 1458a8aef622SOliver Neukum static int usbtouch_reset_resume(struct usb_interface *intf) 1459a8aef622SOliver Neukum { 1460a8aef622SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1461a8aef622SOliver Neukum struct input_dev *input = usbtouch->input; 1462a8aef622SOliver Neukum int err = 0; 1463a8aef622SOliver Neukum 1464a8aef622SOliver Neukum /* reinit the device */ 1465a8aef622SOliver Neukum if (usbtouch->type->init) { 1466a8aef622SOliver Neukum err = usbtouch->type->init(usbtouch); 1467a8aef622SOliver Neukum if (err) { 1468*b741ab9dSGreg Kroah-Hartman dev_dbg(&input->dev, 1469*b741ab9dSGreg Kroah-Hartman "%s - type->init() failed, err: %d\n", 1470a8aef622SOliver Neukum __func__, err); 1471a8aef622SOliver Neukum return err; 1472a8aef622SOliver Neukum } 1473a8aef622SOliver Neukum } 1474a8aef622SOliver Neukum 1475a8aef622SOliver Neukum /* restart IO if needed */ 1476a8aef622SOliver Neukum mutex_lock(&input->mutex); 1477a8aef622SOliver Neukum if (input->users) 1478a8aef622SOliver Neukum err = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1479a8aef622SOliver Neukum mutex_unlock(&input->mutex); 1480a8aef622SOliver Neukum 1481a8aef622SOliver Neukum return err; 1482a8aef622SOliver Neukum } 1483a8aef622SOliver Neukum 1484d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev, 1485d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch) 1486d05e84e6SDmitry Torokhov { 1487997ea58eSDaniel Mack usb_free_coherent(udev, usbtouch->type->rept_size, 1488d05e84e6SDmitry Torokhov usbtouch->data, usbtouch->data_dma); 1489d05e84e6SDmitry Torokhov kfree(usbtouch->buffer); 1490d05e84e6SDmitry Torokhov } 1491d05e84e6SDmitry Torokhov 1492f4a5e359SOndrej Zary static struct usb_endpoint_descriptor * 1493f4a5e359SOndrej Zary usbtouch_get_input_endpoint(struct usb_host_interface *interface) 1494f4a5e359SOndrej Zary { 1495f4a5e359SOndrej Zary int i; 1496f4a5e359SOndrej Zary 1497f4a5e359SOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) 1498f4a5e359SOndrej Zary if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) 1499f4a5e359SOndrej Zary return &interface->endpoint[i].desc; 1500f4a5e359SOndrej Zary 1501f4a5e359SOndrej Zary return NULL; 1502f4a5e359SOndrej Zary } 1503d05e84e6SDmitry Torokhov 1504d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf, 1505d05e84e6SDmitry Torokhov const struct usb_device_id *id) 1506d05e84e6SDmitry Torokhov { 1507d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch; 1508d05e84e6SDmitry Torokhov struct input_dev *input_dev; 1509d05e84e6SDmitry Torokhov struct usb_endpoint_descriptor *endpoint; 1510d05e84e6SDmitry Torokhov struct usb_device *udev = interface_to_usbdev(intf); 1511d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 1512d05e84e6SDmitry Torokhov int err = -ENOMEM; 1513d05e84e6SDmitry Torokhov 1514ec42d448SDaniel Ritz /* some devices are ignored */ 1515ec42d448SDaniel Ritz if (id->driver_info == DEVTYPE_IGNORE) 1516ec42d448SDaniel Ritz return -ENODEV; 1517ec42d448SDaniel Ritz 1518f4a5e359SOndrej Zary endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); 1519f4a5e359SOndrej Zary if (!endpoint) 1520f4a5e359SOndrej Zary return -ENXIO; 1521d05e84e6SDmitry Torokhov 1522d05e84e6SDmitry Torokhov usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 1523d05e84e6SDmitry Torokhov input_dev = input_allocate_device(); 1524d05e84e6SDmitry Torokhov if (!usbtouch || !input_dev) 1525d05e84e6SDmitry Torokhov goto out_free; 1526d05e84e6SDmitry Torokhov 1527d05e84e6SDmitry Torokhov type = &usbtouch_dev_info[id->driver_info]; 1528d05e84e6SDmitry Torokhov usbtouch->type = type; 1529d05e84e6SDmitry Torokhov if (!type->process_pkt) 1530d05e84e6SDmitry Torokhov type->process_pkt = usbtouch_process_pkt; 1531d05e84e6SDmitry Torokhov 1532997ea58eSDaniel Mack usbtouch->data = usb_alloc_coherent(udev, type->rept_size, 1533d05e84e6SDmitry Torokhov GFP_KERNEL, &usbtouch->data_dma); 1534d05e84e6SDmitry Torokhov if (!usbtouch->data) 1535d05e84e6SDmitry Torokhov goto out_free; 1536d05e84e6SDmitry Torokhov 153762aa366dSDaniel Ritz if (type->get_pkt_len) { 1538d05e84e6SDmitry Torokhov usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 1539d05e84e6SDmitry Torokhov if (!usbtouch->buffer) 1540d05e84e6SDmitry Torokhov goto out_free_buffers; 1541d05e84e6SDmitry Torokhov } 1542d05e84e6SDmitry Torokhov 1543d05e84e6SDmitry Torokhov usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 1544d05e84e6SDmitry Torokhov if (!usbtouch->irq) { 1545*b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1546*b741ab9dSGreg Kroah-Hartman "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__); 1547d05e84e6SDmitry Torokhov goto out_free_buffers; 1548d05e84e6SDmitry Torokhov } 1549d05e84e6SDmitry Torokhov 1550fea4d14bSOndrej Zary usbtouch->interface = intf; 1551d05e84e6SDmitry Torokhov usbtouch->input = input_dev; 1552d05e84e6SDmitry Torokhov 1553d05e84e6SDmitry Torokhov if (udev->manufacturer) 1554d05e84e6SDmitry Torokhov strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 1555d05e84e6SDmitry Torokhov 1556d05e84e6SDmitry Torokhov if (udev->product) { 1557d05e84e6SDmitry Torokhov if (udev->manufacturer) 1558d05e84e6SDmitry Torokhov strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 1559d05e84e6SDmitry Torokhov strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 1560d05e84e6SDmitry Torokhov } 1561d05e84e6SDmitry Torokhov 1562d05e84e6SDmitry Torokhov if (!strlen(usbtouch->name)) 1563d05e84e6SDmitry Torokhov snprintf(usbtouch->name, sizeof(usbtouch->name), 1564d05e84e6SDmitry Torokhov "USB Touchscreen %04x:%04x", 1565d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idVendor), 1566d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idProduct)); 1567d05e84e6SDmitry Torokhov 1568d05e84e6SDmitry Torokhov usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 15697b6dff98SVladimir Shebordaev strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 1570d05e84e6SDmitry Torokhov 1571d05e84e6SDmitry Torokhov input_dev->name = usbtouch->name; 1572d05e84e6SDmitry Torokhov input_dev->phys = usbtouch->phys; 1573d05e84e6SDmitry Torokhov usb_to_input_id(udev, &input_dev->id); 1574d05e84e6SDmitry Torokhov input_dev->dev.parent = &intf->dev; 1575d05e84e6SDmitry Torokhov 1576d05e84e6SDmitry Torokhov input_set_drvdata(input_dev, usbtouch); 1577d05e84e6SDmitry Torokhov 1578d05e84e6SDmitry Torokhov input_dev->open = usbtouch_open; 1579d05e84e6SDmitry Torokhov input_dev->close = usbtouch_close; 1580d05e84e6SDmitry Torokhov 15817b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 15827b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1583d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 1584d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 1585d05e84e6SDmitry Torokhov if (type->max_press) 1586d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 1587d05e84e6SDmitry Torokhov type->max_press, 0, 0); 1588d05e84e6SDmitry Torokhov 15895197424cSOndrej Zary if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) 1590fea4d14bSOndrej Zary usb_fill_int_urb(usbtouch->irq, udev, 1591fea4d14bSOndrej Zary usb_rcvintpipe(udev, endpoint->bEndpointAddress), 1592d05e84e6SDmitry Torokhov usbtouch->data, type->rept_size, 1593d05e84e6SDmitry Torokhov usbtouch_irq, usbtouch, endpoint->bInterval); 15945197424cSOndrej Zary else 15955197424cSOndrej Zary usb_fill_bulk_urb(usbtouch->irq, udev, 15965197424cSOndrej Zary usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), 15975197424cSOndrej Zary usbtouch->data, type->rept_size, 15985197424cSOndrej Zary usbtouch_irq, usbtouch); 1599d05e84e6SDmitry Torokhov 1600fea4d14bSOndrej Zary usbtouch->irq->dev = udev; 1601d05e84e6SDmitry Torokhov usbtouch->irq->transfer_dma = usbtouch->data_dma; 1602d05e84e6SDmitry Torokhov usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1603d05e84e6SDmitry Torokhov 1604a8aef622SOliver Neukum /* device specific allocations */ 1605a8aef622SOliver Neukum if (type->alloc) { 1606a8aef622SOliver Neukum err = type->alloc(usbtouch); 1607a8aef622SOliver Neukum if (err) { 1608*b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1609*b741ab9dSGreg Kroah-Hartman "%s - type->alloc() failed, err: %d\n", 1610*b741ab9dSGreg Kroah-Hartman __func__, err); 1611a8aef622SOliver Neukum goto out_free_urb; 1612a8aef622SOliver Neukum } 1613a8aef622SOliver Neukum } 1614a8aef622SOliver Neukum 1615a8aef622SOliver Neukum /* device specific initialisation*/ 1616d05e84e6SDmitry Torokhov if (type->init) { 1617d05e84e6SDmitry Torokhov err = type->init(usbtouch); 1618d05e84e6SDmitry Torokhov if (err) { 1619*b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1620*b741ab9dSGreg Kroah-Hartman "%s - type->init() failed, err: %d\n", 1621*b741ab9dSGreg Kroah-Hartman __func__, err); 1622a8aef622SOliver Neukum goto out_do_exit; 1623d05e84e6SDmitry Torokhov } 1624d05e84e6SDmitry Torokhov } 1625d05e84e6SDmitry Torokhov 1626d05e84e6SDmitry Torokhov err = input_register_device(usbtouch->input); 1627d05e84e6SDmitry Torokhov if (err) { 1628*b741ab9dSGreg Kroah-Hartman dev_dbg(&intf->dev, 1629*b741ab9dSGreg Kroah-Hartman "%s - input_register_device failed, err: %d\n", 1630*b741ab9dSGreg Kroah-Hartman __func__, err); 16315197424cSOndrej Zary goto out_do_exit; 1632d05e84e6SDmitry Torokhov } 1633d05e84e6SDmitry Torokhov 1634d05e84e6SDmitry Torokhov usb_set_intfdata(intf, usbtouch); 1635d05e84e6SDmitry Torokhov 16361e87a430SOndrej Zary if (usbtouch->type->irq_always) { 16375d9efc59SOliver Neukum /* this can't fail */ 16385d9efc59SOliver Neukum usb_autopm_get_interface(intf); 16391e87a430SOndrej Zary err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); 16401e87a430SOndrej Zary if (err) { 16415d9efc59SOliver Neukum usb_autopm_put_interface(intf); 1642f864b60aSGreg Kroah-Hartman dev_err(&input_dev->dev, 1643e27ad0feSGreg Kroah-Hartman "%s - usb_submit_urb failed with result: %d\n", 16441e87a430SOndrej Zary __func__, err); 16451e87a430SOndrej Zary goto out_unregister_input; 16461e87a430SOndrej Zary } 16471e87a430SOndrej Zary } 16482330ed18SDaniel Silverstone 1649d05e84e6SDmitry Torokhov return 0; 1650d05e84e6SDmitry Torokhov 16511e87a430SOndrej Zary out_unregister_input: 16521e87a430SOndrej Zary input_unregister_device(input_dev); 16531e87a430SOndrej Zary input_dev = NULL; 16545197424cSOndrej Zary out_do_exit: 16555197424cSOndrej Zary if (type->exit) 16565197424cSOndrej Zary type->exit(usbtouch); 16571e87a430SOndrej Zary out_free_urb: 16581e87a430SOndrej Zary usb_free_urb(usbtouch->irq); 1659d05e84e6SDmitry Torokhov out_free_buffers: 1660d05e84e6SDmitry Torokhov usbtouch_free_buffers(udev, usbtouch); 1661d05e84e6SDmitry Torokhov out_free: 1662d05e84e6SDmitry Torokhov input_free_device(input_dev); 1663d05e84e6SDmitry Torokhov kfree(usbtouch); 1664d05e84e6SDmitry Torokhov return err; 1665d05e84e6SDmitry Torokhov } 1666d05e84e6SDmitry Torokhov 1667d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf) 1668d05e84e6SDmitry Torokhov { 1669d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1670d05e84e6SDmitry Torokhov 1671d05e84e6SDmitry Torokhov if (!usbtouch) 1672d05e84e6SDmitry Torokhov return; 1673d05e84e6SDmitry Torokhov 1674*b741ab9dSGreg Kroah-Hartman dev_dbg(&usbtouch->input->dev, 1675*b741ab9dSGreg Kroah-Hartman "%s - usbtouch is initialized, cleaning up\n", __func__); 1676*b741ab9dSGreg Kroah-Hartman 1677d05e84e6SDmitry Torokhov usb_set_intfdata(intf, NULL); 1678722232bcSOliver Neukum /* this will stop IO via close */ 1679d05e84e6SDmitry Torokhov input_unregister_device(usbtouch->input); 1680d05e84e6SDmitry Torokhov usb_free_urb(usbtouch->irq); 16815197424cSOndrej Zary if (usbtouch->type->exit) 16825197424cSOndrej Zary usbtouch->type->exit(usbtouch); 1683d05e84e6SDmitry Torokhov usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 1684d05e84e6SDmitry Torokhov kfree(usbtouch); 1685d05e84e6SDmitry Torokhov } 1686d05e84e6SDmitry Torokhov 1687d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices); 1688d05e84e6SDmitry Torokhov 1689d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = { 1690d05e84e6SDmitry Torokhov .name = "usbtouchscreen", 1691d05e84e6SDmitry Torokhov .probe = usbtouch_probe, 1692d05e84e6SDmitry Torokhov .disconnect = usbtouch_disconnect, 1693ed4299e1SOliver Neukum .suspend = usbtouch_suspend, 1694ed4299e1SOliver Neukum .resume = usbtouch_resume, 1695a8aef622SOliver Neukum .reset_resume = usbtouch_reset_resume, 1696d05e84e6SDmitry Torokhov .id_table = usbtouch_devices, 16975d9efc59SOliver Neukum .supports_autosuspend = 1, 1698d05e84e6SDmitry Torokhov }; 1699d05e84e6SDmitry Torokhov 170008642e7cSGreg Kroah-Hartman module_usb_driver(usbtouch_driver); 1701d05e84e6SDmitry Torokhov 1702d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR); 1703d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC); 1704d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL"); 1705d05e84e6SDmitry Torokhov 1706d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb"); 1707d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch"); 1708d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb"); 1709