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 17d05e84e6SDmitry Torokhov * 1814e40206SJerrold Jones * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 19d05e84e6SDmitry Torokhov * Copyright (C) by Todd E. Johnson (mtouchusb.c) 20d05e84e6SDmitry Torokhov * 21d05e84e6SDmitry Torokhov * This program is free software; you can redistribute it and/or 22d05e84e6SDmitry Torokhov * modify it under the terms of the GNU General Public License as 23d05e84e6SDmitry Torokhov * published by the Free Software Foundation; either version 2 of the 24d05e84e6SDmitry Torokhov * License, or (at your option) any later version. 25d05e84e6SDmitry Torokhov * 26d05e84e6SDmitry Torokhov * This program is distributed in the hope that it will be useful, but 27d05e84e6SDmitry Torokhov * WITHOUT ANY WARRANTY; without even the implied warranty of 28d05e84e6SDmitry Torokhov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29d05e84e6SDmitry Torokhov * General Public License for more details. 30d05e84e6SDmitry Torokhov * 31d05e84e6SDmitry Torokhov * You should have received a copy of the GNU General Public License 32d05e84e6SDmitry Torokhov * along with this program; if not, write to the Free Software 33d05e84e6SDmitry Torokhov * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 34d05e84e6SDmitry Torokhov * 35d05e84e6SDmitry Torokhov * Driver is based on touchkitusb.c 36d05e84e6SDmitry Torokhov * - ITM parts are from itmtouch.c 37d05e84e6SDmitry Torokhov * - 3M parts are from mtouchusb.c 38d05e84e6SDmitry Torokhov * - PanJit parts are from an unmerged driver by Lanslott Gish 39d05e84e6SDmitry Torokhov * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged 40d05e84e6SDmitry Torokhov * driver from Marius Vollmer 41d05e84e6SDmitry Torokhov * 42d05e84e6SDmitry Torokhov *****************************************************************************/ 43d05e84e6SDmitry Torokhov 44d05e84e6SDmitry Torokhov //#define DEBUG 45d05e84e6SDmitry Torokhov 46d05e84e6SDmitry Torokhov #include <linux/kernel.h> 47d05e84e6SDmitry Torokhov #include <linux/slab.h> 48d05e84e6SDmitry Torokhov #include <linux/input.h> 49d05e84e6SDmitry Torokhov #include <linux/module.h> 50d05e84e6SDmitry Torokhov #include <linux/init.h> 51d05e84e6SDmitry Torokhov #include <linux/usb.h> 52d05e84e6SDmitry Torokhov #include <linux/usb/input.h> 53ec42d448SDaniel Ritz #include <linux/hid.h> 54d05e84e6SDmitry Torokhov 55d05e84e6SDmitry Torokhov 5662aa366dSDaniel Ritz #define DRIVER_VERSION "v0.6" 57d05e84e6SDmitry Torokhov #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 58d05e84e6SDmitry Torokhov #define DRIVER_DESC "USB Touchscreen Driver" 59d05e84e6SDmitry Torokhov 60d05e84e6SDmitry Torokhov static int swap_xy; 61d05e84e6SDmitry Torokhov module_param(swap_xy, bool, 0644); 62d05e84e6SDmitry Torokhov MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 63d05e84e6SDmitry Torokhov 64c9cbf3d3SDan Streetman static int hwcalib_xy; 65c9cbf3d3SDan Streetman module_param(hwcalib_xy, bool, 0644); 66c9cbf3d3SDan Streetman MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); 67c9cbf3d3SDan Streetman 68d05e84e6SDmitry Torokhov /* device specifc data/functions */ 69d05e84e6SDmitry Torokhov struct usbtouch_usb; 70d05e84e6SDmitry Torokhov struct usbtouch_device_info { 71d05e84e6SDmitry Torokhov int min_xc, max_xc; 72d05e84e6SDmitry Torokhov int min_yc, max_yc; 73d05e84e6SDmitry Torokhov int min_press, max_press; 74d05e84e6SDmitry Torokhov int rept_size; 75d05e84e6SDmitry Torokhov 76d05e84e6SDmitry Torokhov void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); 7762aa366dSDaniel Ritz 7862aa366dSDaniel Ritz /* 7962aa366dSDaniel Ritz * used to get the packet len. possible return values: 8062aa366dSDaniel Ritz * > 0: packet len 8162aa366dSDaniel Ritz * = 0: skip one byte 8262aa366dSDaniel Ritz * < 0: -return value more bytes needed 8362aa366dSDaniel Ritz */ 84d05e84e6SDmitry Torokhov int (*get_pkt_len) (unsigned char *pkt, int len); 8562aa366dSDaniel Ritz 86d05e84e6SDmitry Torokhov int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); 87d05e84e6SDmitry Torokhov int (*init) (struct usbtouch_usb *usbtouch); 88d05e84e6SDmitry Torokhov }; 89d05e84e6SDmitry Torokhov 90d05e84e6SDmitry Torokhov /* a usbtouch device */ 91d05e84e6SDmitry Torokhov struct usbtouch_usb { 92d05e84e6SDmitry Torokhov unsigned char *data; 93d05e84e6SDmitry Torokhov dma_addr_t data_dma; 94d05e84e6SDmitry Torokhov unsigned char *buffer; 95d05e84e6SDmitry Torokhov int buf_len; 96d05e84e6SDmitry Torokhov struct urb *irq; 97d05e84e6SDmitry Torokhov struct usb_device *udev; 98d05e84e6SDmitry Torokhov struct input_dev *input; 99d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 100d05e84e6SDmitry Torokhov char name[128]; 101d05e84e6SDmitry Torokhov char phys[64]; 102d05e84e6SDmitry Torokhov 103d05e84e6SDmitry Torokhov int x, y; 104d05e84e6SDmitry Torokhov int touch, press; 105d05e84e6SDmitry Torokhov }; 106d05e84e6SDmitry Torokhov 107d05e84e6SDmitry Torokhov 108d05e84e6SDmitry Torokhov /* device types */ 109d05e84e6SDmitry Torokhov enum { 110ec42d448SDaniel Ritz DEVTYPE_IGNORE = -1, 111d05e84e6SDmitry Torokhov DEVTYPE_EGALAX, 112d05e84e6SDmitry Torokhov DEVTYPE_PANJIT, 113d05e84e6SDmitry Torokhov DEVTYPE_3M, 114d05e84e6SDmitry Torokhov DEVTYPE_ITM, 115d05e84e6SDmitry Torokhov DEVTYPE_ETURBO, 116d05e84e6SDmitry Torokhov DEVTYPE_GUNZE, 117d05e84e6SDmitry Torokhov DEVTYPE_DMC_TSC10, 118df561fcdSOndrej Zary DEVTYPE_IRTOUCH, 119a14a8401SOndrej Zary DEVTYPE_IDEALTEK, 1209d5657dbSIlya Frolov DEVTYPE_GENERAL_TOUCH, 12114e40206SJerrold Jones DEVTYPE_GOTOP, 122f7370699SJim Persson DEVTYPE_JASTEC, 123*9e3b2583SFlorian Echtler DEVTYPE_E2I, 124d05e84e6SDmitry Torokhov }; 125d05e84e6SDmitry Torokhov 126ec42d448SDaniel Ritz #define USB_DEVICE_HID_CLASS(vend, prod) \ 127ec42d448SDaniel Ritz .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ 128139ebe8dSDaniel Ritz | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ 129ec42d448SDaniel Ritz | USB_DEVICE_ID_MATCH_DEVICE, \ 130ec42d448SDaniel Ritz .idVendor = (vend), \ 131ec42d448SDaniel Ritz .idProduct = (prod), \ 132ec42d448SDaniel Ritz .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 133ec42d448SDaniel Ritz .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE 134ec42d448SDaniel Ritz 135d05e84e6SDmitry Torokhov static struct usb_device_id usbtouch_devices[] = { 136c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 137ec42d448SDaniel Ritz /* ignore the HID capable devices, handled by usbhid */ 138ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 139ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 140ec42d448SDaniel Ritz 141ec42d448SDaniel Ritz /* normal device IDs */ 142d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 143d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 144d05e84e6SDmitry Torokhov {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 145d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 146d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 147d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 148d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 149d05e84e6SDmitry Torokhov #endif 150d05e84e6SDmitry Torokhov 151c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 152d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 153d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 154d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 155d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 156d05e84e6SDmitry Torokhov #endif 157d05e84e6SDmitry Torokhov 158c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 159d05e84e6SDmitry Torokhov {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 160d05e84e6SDmitry Torokhov #endif 161d05e84e6SDmitry Torokhov 162c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 163d05e84e6SDmitry Torokhov {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 164d05e84e6SDmitry Torokhov #endif 165d05e84e6SDmitry Torokhov 166c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 167d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 168d05e84e6SDmitry Torokhov #endif 169d05e84e6SDmitry Torokhov 170c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 171d05e84e6SDmitry Torokhov {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 172d05e84e6SDmitry Torokhov #endif 173d05e84e6SDmitry Torokhov 174c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 175d05e84e6SDmitry Torokhov {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 176d05e84e6SDmitry Torokhov #endif 177d05e84e6SDmitry Torokhov 178df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 179df561fcdSOndrej Zary {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 180df561fcdSOndrej Zary {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 181df561fcdSOndrej Zary #endif 182df561fcdSOndrej Zary 183a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 184a14a8401SOndrej Zary {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 185a14a8401SOndrej Zary #endif 186a14a8401SOndrej Zary 1879d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 1889d5657dbSIlya Frolov {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 1899d5657dbSIlya Frolov #endif 1909d5657dbSIlya Frolov 19114e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 19214e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 19314e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 19414e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 19514e40206SJerrold Jones #endif 19614e40206SJerrold Jones 197f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 198f7370699SJim Persson {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, 199f7370699SJim Persson #endif 200f7370699SJim Persson 201*9e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 202*9e3b2583SFlorian Echtler {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, 203*9e3b2583SFlorian Echtler #endif 204d05e84e6SDmitry Torokhov {} 205d05e84e6SDmitry Torokhov }; 206d05e84e6SDmitry Torokhov 207d05e84e6SDmitry Torokhov 208d05e84e6SDmitry Torokhov /***************************************************************************** 209*9e3b2583SFlorian Echtler * e2i Part 210*9e3b2583SFlorian Echtler */ 211*9e3b2583SFlorian Echtler 212*9e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 213*9e3b2583SFlorian Echtler static int e2i_init(struct usbtouch_usb *usbtouch) 214*9e3b2583SFlorian Echtler { 215*9e3b2583SFlorian Echtler int ret; 216*9e3b2583SFlorian Echtler 217*9e3b2583SFlorian Echtler ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 218*9e3b2583SFlorian Echtler 0x01, 0x02, 0x0000, 0x0081, 219*9e3b2583SFlorian Echtler NULL, 0, USB_CTRL_SET_TIMEOUT); 220*9e3b2583SFlorian Echtler 221*9e3b2583SFlorian Echtler dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", 222*9e3b2583SFlorian Echtler __func__, ret); 223*9e3b2583SFlorian Echtler return ret; 224*9e3b2583SFlorian Echtler } 225*9e3b2583SFlorian Echtler 226*9e3b2583SFlorian Echtler static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 227*9e3b2583SFlorian Echtler { 228*9e3b2583SFlorian Echtler int tmp = (pkt[0] << 8) | pkt[1]; 229*9e3b2583SFlorian Echtler dev->x = (pkt[2] << 8) | pkt[3]; 230*9e3b2583SFlorian Echtler dev->y = (pkt[4] << 8) | pkt[5]; 231*9e3b2583SFlorian Echtler 232*9e3b2583SFlorian Echtler tmp = tmp - 0xA000; 233*9e3b2583SFlorian Echtler dev->touch = (tmp > 0); 234*9e3b2583SFlorian Echtler dev->press = (tmp > 0 ? tmp : 0); 235*9e3b2583SFlorian Echtler 236*9e3b2583SFlorian Echtler return 1; 237*9e3b2583SFlorian Echtler } 238*9e3b2583SFlorian Echtler #endif 239*9e3b2583SFlorian Echtler 240*9e3b2583SFlorian Echtler 241*9e3b2583SFlorian Echtler /***************************************************************************** 242d05e84e6SDmitry Torokhov * eGalax part 243d05e84e6SDmitry Torokhov */ 244d05e84e6SDmitry Torokhov 245c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 246d05e84e6SDmitry Torokhov 24762aa366dSDaniel Ritz #ifndef MULTI_PACKET 24862aa366dSDaniel Ritz #define MULTI_PACKET 24962aa366dSDaniel Ritz #endif 25062aa366dSDaniel Ritz 251d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK 0xFE 252d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT 0x80 253d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG 0x0A 254d05e84e6SDmitry Torokhov 255d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 256d05e84e6SDmitry Torokhov { 257d05e84e6SDmitry Torokhov if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 258d05e84e6SDmitry Torokhov return 0; 259d05e84e6SDmitry Torokhov 260d05e84e6SDmitry Torokhov dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 261d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 262d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 263d05e84e6SDmitry Torokhov 264d05e84e6SDmitry Torokhov return 1; 265d05e84e6SDmitry Torokhov } 266d05e84e6SDmitry Torokhov 267d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len) 268d05e84e6SDmitry Torokhov { 269d05e84e6SDmitry Torokhov switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 270d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_REPT: 271d05e84e6SDmitry Torokhov return 5; 272d05e84e6SDmitry Torokhov 273d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_DIAG: 274d05e84e6SDmitry Torokhov if (len < 2) 275d05e84e6SDmitry Torokhov return -1; 276d05e84e6SDmitry Torokhov 277d05e84e6SDmitry Torokhov return buf[1] + 2; 278d05e84e6SDmitry Torokhov } 279d05e84e6SDmitry Torokhov 280d05e84e6SDmitry Torokhov return 0; 281d05e84e6SDmitry Torokhov } 282d05e84e6SDmitry Torokhov #endif 283d05e84e6SDmitry Torokhov 284d05e84e6SDmitry Torokhov 285d05e84e6SDmitry Torokhov /***************************************************************************** 286d05e84e6SDmitry Torokhov * PanJit Part 287d05e84e6SDmitry Torokhov */ 288c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 289d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 290d05e84e6SDmitry Torokhov { 291d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 292d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 293d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 294d05e84e6SDmitry Torokhov 295d05e84e6SDmitry Torokhov return 1; 296d05e84e6SDmitry Torokhov } 297d05e84e6SDmitry Torokhov #endif 298d05e84e6SDmitry Torokhov 299d05e84e6SDmitry Torokhov 300d05e84e6SDmitry Torokhov /***************************************************************************** 301d05e84e6SDmitry Torokhov * 3M/Microtouch Part 302d05e84e6SDmitry Torokhov */ 303c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 304d05e84e6SDmitry Torokhov 305d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT 1 306d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET 7 307d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID 10 308d05e84e6SDmitry Torokhov 309d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 310d05e84e6SDmitry Torokhov { 311c9cbf3d3SDan Streetman if (hwcalib_xy) { 312c9cbf3d3SDan Streetman dev->x = (pkt[4] << 8) | pkt[3]; 313c9cbf3d3SDan Streetman dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 314c9cbf3d3SDan Streetman } else { 315d05e84e6SDmitry Torokhov dev->x = (pkt[8] << 8) | pkt[7]; 316d05e84e6SDmitry Torokhov dev->y = (pkt[10] << 8) | pkt[9]; 317c9cbf3d3SDan Streetman } 318d05e84e6SDmitry Torokhov dev->touch = (pkt[2] & 0x40) ? 1 : 0; 319d05e84e6SDmitry Torokhov 320d05e84e6SDmitry Torokhov return 1; 321d05e84e6SDmitry Torokhov } 322d05e84e6SDmitry Torokhov 323d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch) 324d05e84e6SDmitry Torokhov { 325d05e84e6SDmitry Torokhov int ret, i; 326d05e84e6SDmitry Torokhov 327d05e84e6SDmitry Torokhov ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 328d05e84e6SDmitry Torokhov MTOUCHUSB_RESET, 329d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 330d05e84e6SDmitry Torokhov 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 331d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", 332ea3e6c59SHarvey Harrison __func__, ret); 333d05e84e6SDmitry Torokhov if (ret < 0) 334d05e84e6SDmitry Torokhov return ret; 335d05e84e6SDmitry Torokhov msleep(150); 336d05e84e6SDmitry Torokhov 337d05e84e6SDmitry Torokhov for (i = 0; i < 3; i++) { 338d05e84e6SDmitry Torokhov ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 339d05e84e6SDmitry Torokhov MTOUCHUSB_ASYNC_REPORT, 340d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 341d05e84e6SDmitry Torokhov 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 342d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", 343ea3e6c59SHarvey Harrison __func__, ret); 344d05e84e6SDmitry Torokhov if (ret >= 0) 345d05e84e6SDmitry Torokhov break; 346d05e84e6SDmitry Torokhov if (ret != -EPIPE) 347d05e84e6SDmitry Torokhov return ret; 348d05e84e6SDmitry Torokhov } 349d05e84e6SDmitry Torokhov 350c9cbf3d3SDan Streetman /* Default min/max xy are the raw values, override if using hw-calib */ 351c9cbf3d3SDan Streetman if (hwcalib_xy) { 352c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 353c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 354c9cbf3d3SDan Streetman } 355c9cbf3d3SDan Streetman 356d05e84e6SDmitry Torokhov return 0; 357d05e84e6SDmitry Torokhov } 358d05e84e6SDmitry Torokhov #endif 359d05e84e6SDmitry Torokhov 360d05e84e6SDmitry Torokhov 361d05e84e6SDmitry Torokhov /***************************************************************************** 362d05e84e6SDmitry Torokhov * ITM Part 363d05e84e6SDmitry Torokhov */ 364c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 365d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 366d05e84e6SDmitry Torokhov { 367d05e84e6SDmitry Torokhov int touch; 368d05e84e6SDmitry Torokhov /* 369d05e84e6SDmitry Torokhov * ITM devices report invalid x/y data if not touched. 370d05e84e6SDmitry Torokhov * if the screen was touched before but is not touched any more 371d05e84e6SDmitry Torokhov * report touch as 0 with the last valid x/y data once. then stop 372d05e84e6SDmitry Torokhov * reporting data until touched again. 373d05e84e6SDmitry Torokhov */ 374d05e84e6SDmitry Torokhov dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 375d05e84e6SDmitry Torokhov 376d05e84e6SDmitry Torokhov touch = ~pkt[7] & 0x20; 377d05e84e6SDmitry Torokhov if (!touch) { 378d05e84e6SDmitry Torokhov if (dev->touch) { 379d05e84e6SDmitry Torokhov dev->touch = 0; 380d05e84e6SDmitry Torokhov return 1; 381d05e84e6SDmitry Torokhov } 382d05e84e6SDmitry Torokhov 383d05e84e6SDmitry Torokhov return 0; 384d05e84e6SDmitry Torokhov } 385d05e84e6SDmitry Torokhov 386d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 387d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 388d05e84e6SDmitry Torokhov dev->touch = touch; 389d05e84e6SDmitry Torokhov 390d05e84e6SDmitry Torokhov return 1; 391d05e84e6SDmitry Torokhov } 392d05e84e6SDmitry Torokhov #endif 393d05e84e6SDmitry Torokhov 394d05e84e6SDmitry Torokhov 395d05e84e6SDmitry Torokhov /***************************************************************************** 396d05e84e6SDmitry Torokhov * eTurboTouch part 397d05e84e6SDmitry Torokhov */ 398c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 39962aa366dSDaniel Ritz #ifndef MULTI_PACKET 40062aa366dSDaniel Ritz #define MULTI_PACKET 40162aa366dSDaniel Ritz #endif 402d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 403d05e84e6SDmitry Torokhov { 404d05e84e6SDmitry Torokhov unsigned int shift; 405d05e84e6SDmitry Torokhov 406d05e84e6SDmitry Torokhov /* packets should start with sync */ 407d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80)) 408d05e84e6SDmitry Torokhov return 0; 409d05e84e6SDmitry Torokhov 410d05e84e6SDmitry Torokhov shift = (6 - (pkt[0] & 0x03)); 411d05e84e6SDmitry Torokhov dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 412d05e84e6SDmitry Torokhov dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 413d05e84e6SDmitry Torokhov dev->touch = (pkt[0] & 0x10) ? 1 : 0; 414d05e84e6SDmitry Torokhov 415d05e84e6SDmitry Torokhov return 1; 416d05e84e6SDmitry Torokhov } 417d05e84e6SDmitry Torokhov 418d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len) 419d05e84e6SDmitry Torokhov { 420d05e84e6SDmitry Torokhov if (buf[0] & 0x80) 421d05e84e6SDmitry Torokhov return 5; 422d05e84e6SDmitry Torokhov if (buf[0] == 0x01) 423d05e84e6SDmitry Torokhov return 3; 424d05e84e6SDmitry Torokhov return 0; 425d05e84e6SDmitry Torokhov } 426d05e84e6SDmitry Torokhov #endif 427d05e84e6SDmitry Torokhov 428d05e84e6SDmitry Torokhov 429d05e84e6SDmitry Torokhov /***************************************************************************** 430d05e84e6SDmitry Torokhov * Gunze part 431d05e84e6SDmitry Torokhov */ 432c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 433d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 434d05e84e6SDmitry Torokhov { 435d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 436d05e84e6SDmitry Torokhov return 0; 437d05e84e6SDmitry Torokhov 438d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 439d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 440d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x20; 441d05e84e6SDmitry Torokhov 442d05e84e6SDmitry Torokhov return 1; 443d05e84e6SDmitry Torokhov } 444d05e84e6SDmitry Torokhov #endif 445d05e84e6SDmitry Torokhov 446d05e84e6SDmitry Torokhov /***************************************************************************** 447d05e84e6SDmitry Torokhov * DMC TSC-10/25 Part 448d05e84e6SDmitry Torokhov * 449d05e84e6SDmitry Torokhov * Documentation about the controller and it's protocol can be found at 450d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 451d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 452d05e84e6SDmitry Torokhov */ 453c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 454d05e84e6SDmitry Torokhov 455d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */ 456d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT 0x50 457d05e84e6SDmitry Torokhov #define TSC10_RATE_30 0x40 458d05e84e6SDmitry Torokhov #define TSC10_RATE_50 0x41 459d05e84e6SDmitry Torokhov #define TSC10_RATE_80 0x42 460d05e84e6SDmitry Torokhov #define TSC10_RATE_100 0x43 461d05e84e6SDmitry Torokhov #define TSC10_RATE_130 0x44 462d05e84e6SDmitry Torokhov #define TSC10_RATE_150 0x45 463d05e84e6SDmitry Torokhov 464d05e84e6SDmitry Torokhov /* commands */ 465d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET 0x55 466d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE 0x05 467d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1 0x01 468d05e84e6SDmitry Torokhov 469d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 470d05e84e6SDmitry Torokhov { 471d05e84e6SDmitry Torokhov struct usb_device *dev = usbtouch->udev; 47276d057ceSOliver Neukum int ret = -ENOMEM; 47376d057ceSOliver Neukum unsigned char *buf; 474d05e84e6SDmitry Torokhov 47576d057ceSOliver Neukum buf = kmalloc(2, GFP_KERNEL); 47676d057ceSOliver Neukum if (!buf) 47776d057ceSOliver Neukum goto err_nobuf; 478d05e84e6SDmitry Torokhov /* reset */ 479d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 480d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 481d05e84e6SDmitry Torokhov TSC10_CMD_RESET, 482d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 483d05e84e6SDmitry Torokhov 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 484d05e84e6SDmitry Torokhov if (ret < 0) 48576d057ceSOliver Neukum goto err_out; 4862ec6f246SNuno Lucas if (buf[0] != 0x06) { 48776d057ceSOliver Neukum ret = -ENODEV; 48876d057ceSOliver Neukum goto err_out; 48976d057ceSOliver Neukum } 490d05e84e6SDmitry Torokhov 491d05e84e6SDmitry Torokhov /* set coordinate output rate */ 492d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 493d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 494d05e84e6SDmitry Torokhov TSC10_CMD_RATE, 495d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 496d05e84e6SDmitry Torokhov TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 497d05e84e6SDmitry Torokhov if (ret < 0) 49876d057ceSOliver Neukum goto err_out; 4992ec6f246SNuno Lucas if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 50076d057ceSOliver Neukum ret = -ENODEV; 50176d057ceSOliver Neukum goto err_out; 50276d057ceSOliver Neukum } 503d05e84e6SDmitry Torokhov 504d05e84e6SDmitry Torokhov /* start sending data */ 505d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 506d05e84e6SDmitry Torokhov TSC10_CMD_DATA1, 507d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 508d05e84e6SDmitry Torokhov 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 50976d057ceSOliver Neukum err_out: 51076d057ceSOliver Neukum kfree(buf); 51176d057ceSOliver Neukum err_nobuf: 512d05e84e6SDmitry Torokhov return ret; 513d05e84e6SDmitry Torokhov } 514d05e84e6SDmitry Torokhov 515d05e84e6SDmitry Torokhov 516d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 517d05e84e6SDmitry Torokhov { 518d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 519d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 520d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 521d05e84e6SDmitry Torokhov 522d05e84e6SDmitry Torokhov return 1; 523d05e84e6SDmitry Torokhov } 524d05e84e6SDmitry Torokhov #endif 525d05e84e6SDmitry Torokhov 526d05e84e6SDmitry Torokhov 527d05e84e6SDmitry Torokhov /***************************************************************************** 528df561fcdSOndrej Zary * IRTOUCH Part 529df561fcdSOndrej Zary */ 530df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 531df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 532df561fcdSOndrej Zary { 533df561fcdSOndrej Zary dev->x = (pkt[3] << 8) | pkt[2]; 534df561fcdSOndrej Zary dev->y = (pkt[5] << 8) | pkt[4]; 535df561fcdSOndrej Zary dev->touch = (pkt[1] & 0x03) ? 1 : 0; 536df561fcdSOndrej Zary 537df561fcdSOndrej Zary return 1; 538df561fcdSOndrej Zary } 539df561fcdSOndrej Zary #endif 540df561fcdSOndrej Zary 541df561fcdSOndrej Zary 542df561fcdSOndrej Zary /***************************************************************************** 543a14a8401SOndrej Zary * IdealTEK URTC1000 Part 544a14a8401SOndrej Zary */ 545a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 54662aa366dSDaniel Ritz #ifndef MULTI_PACKET 54762aa366dSDaniel Ritz #define MULTI_PACKET 54862aa366dSDaniel Ritz #endif 549a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len) 550a14a8401SOndrej Zary { 551a14a8401SOndrej Zary if (buf[0] & 0x80) 552a14a8401SOndrej Zary return 5; 553a14a8401SOndrej Zary if (buf[0] == 0x01) 554a14a8401SOndrej Zary return len; 555a14a8401SOndrej Zary return 0; 556a14a8401SOndrej Zary } 557a14a8401SOndrej Zary 558a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 559a14a8401SOndrej Zary { 560a14a8401SOndrej Zary switch (pkt[0] & 0x98) { 561a14a8401SOndrej Zary case 0x88: 562a14a8401SOndrej Zary /* touch data in IdealTEK mode */ 563a14a8401SOndrej Zary dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 564a14a8401SOndrej Zary dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 565a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 566a14a8401SOndrej Zary return 1; 567a14a8401SOndrej Zary 568a14a8401SOndrej Zary case 0x98: 569a14a8401SOndrej Zary /* touch data in MT emulation mode */ 570a14a8401SOndrej Zary dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 571a14a8401SOndrej Zary dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 572a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 573a14a8401SOndrej Zary return 1; 574a14a8401SOndrej Zary 575a14a8401SOndrej Zary default: 576a14a8401SOndrej Zary return 0; 577a14a8401SOndrej Zary } 578a14a8401SOndrej Zary } 579a14a8401SOndrej Zary #endif 580a14a8401SOndrej Zary 5819d5657dbSIlya Frolov /***************************************************************************** 5829d5657dbSIlya Frolov * General Touch Part 5839d5657dbSIlya Frolov */ 5849d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 5859d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 5869d5657dbSIlya Frolov { 5879d5657dbSIlya Frolov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; 5889d5657dbSIlya Frolov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; 5899d5657dbSIlya Frolov dev->press = pkt[5] & 0xff; 5909d5657dbSIlya Frolov dev->touch = pkt[0] & 0x01; 5919d5657dbSIlya Frolov 5929d5657dbSIlya Frolov return 1; 5939d5657dbSIlya Frolov } 5949d5657dbSIlya Frolov #endif 595a14a8401SOndrej Zary 596a14a8401SOndrej Zary /***************************************************************************** 59714e40206SJerrold Jones * GoTop Part 59814e40206SJerrold Jones */ 59914e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 60014e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 60114e40206SJerrold Jones { 60214e40206SJerrold Jones dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 60314e40206SJerrold Jones dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 60414e40206SJerrold Jones dev->touch = pkt[0] & 0x01; 605f7370699SJim Persson 606f7370699SJim Persson return 1; 607f7370699SJim Persson } 608f7370699SJim Persson #endif 609f7370699SJim Persson 610f7370699SJim Persson /***************************************************************************** 611f7370699SJim Persson * JASTEC Part 612f7370699SJim Persson */ 613f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 614f7370699SJim Persson static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 615f7370699SJim Persson { 616f7370699SJim Persson dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); 617f7370699SJim Persson dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); 618f7370699SJim Persson dev->touch = (pkt[0] & 0x40) >> 6; 619f7370699SJim Persson 62014e40206SJerrold Jones return 1; 62114e40206SJerrold Jones } 62214e40206SJerrold Jones #endif 62314e40206SJerrold Jones 62414e40206SJerrold Jones 62514e40206SJerrold Jones /***************************************************************************** 626d05e84e6SDmitry Torokhov * the different device descriptors 627d05e84e6SDmitry Torokhov */ 62862aa366dSDaniel Ritz #ifdef MULTI_PACKET 62962aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 63062aa366dSDaniel Ritz unsigned char *pkt, int len); 63162aa366dSDaniel Ritz #endif 63262aa366dSDaniel Ritz 633d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = { 634c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 635d05e84e6SDmitry Torokhov [DEVTYPE_EGALAX] = { 636d05e84e6SDmitry Torokhov .min_xc = 0x0, 637d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 638d05e84e6SDmitry Torokhov .min_yc = 0x0, 639d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 640d05e84e6SDmitry Torokhov .rept_size = 16, 641d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 642d05e84e6SDmitry Torokhov .get_pkt_len = egalax_get_pkt_len, 643d05e84e6SDmitry Torokhov .read_data = egalax_read_data, 644d05e84e6SDmitry Torokhov }, 645d05e84e6SDmitry Torokhov #endif 646d05e84e6SDmitry Torokhov 647c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 648d05e84e6SDmitry Torokhov [DEVTYPE_PANJIT] = { 649d05e84e6SDmitry Torokhov .min_xc = 0x0, 650d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 651d05e84e6SDmitry Torokhov .min_yc = 0x0, 652d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 653d05e84e6SDmitry Torokhov .rept_size = 8, 654d05e84e6SDmitry Torokhov .read_data = panjit_read_data, 655d05e84e6SDmitry Torokhov }, 656d05e84e6SDmitry Torokhov #endif 657d05e84e6SDmitry Torokhov 658c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 659d05e84e6SDmitry Torokhov [DEVTYPE_3M] = { 660d05e84e6SDmitry Torokhov .min_xc = 0x0, 661d05e84e6SDmitry Torokhov .max_xc = 0x4000, 662d05e84e6SDmitry Torokhov .min_yc = 0x0, 663d05e84e6SDmitry Torokhov .max_yc = 0x4000, 664d05e84e6SDmitry Torokhov .rept_size = 11, 665d05e84e6SDmitry Torokhov .read_data = mtouch_read_data, 666d05e84e6SDmitry Torokhov .init = mtouch_init, 667d05e84e6SDmitry Torokhov }, 668d05e84e6SDmitry Torokhov #endif 669d05e84e6SDmitry Torokhov 670c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 671d05e84e6SDmitry Torokhov [DEVTYPE_ITM] = { 672d05e84e6SDmitry Torokhov .min_xc = 0x0, 673d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 674d05e84e6SDmitry Torokhov .min_yc = 0x0, 675d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 676d05e84e6SDmitry Torokhov .max_press = 0xff, 677d05e84e6SDmitry Torokhov .rept_size = 8, 678d05e84e6SDmitry Torokhov .read_data = itm_read_data, 679d05e84e6SDmitry Torokhov }, 680d05e84e6SDmitry Torokhov #endif 681d05e84e6SDmitry Torokhov 682c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 683d05e84e6SDmitry Torokhov [DEVTYPE_ETURBO] = { 684d05e84e6SDmitry Torokhov .min_xc = 0x0, 685d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 686d05e84e6SDmitry Torokhov .min_yc = 0x0, 687d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 688d05e84e6SDmitry Torokhov .rept_size = 8, 689d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 690d05e84e6SDmitry Torokhov .get_pkt_len = eturbo_get_pkt_len, 691d05e84e6SDmitry Torokhov .read_data = eturbo_read_data, 692d05e84e6SDmitry Torokhov }, 693d05e84e6SDmitry Torokhov #endif 694d05e84e6SDmitry Torokhov 695c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 696d05e84e6SDmitry Torokhov [DEVTYPE_GUNZE] = { 697d05e84e6SDmitry Torokhov .min_xc = 0x0, 698d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 699d05e84e6SDmitry Torokhov .min_yc = 0x0, 700d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 701d05e84e6SDmitry Torokhov .rept_size = 4, 702d05e84e6SDmitry Torokhov .read_data = gunze_read_data, 703d05e84e6SDmitry Torokhov }, 704d05e84e6SDmitry Torokhov #endif 705d05e84e6SDmitry Torokhov 706c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 707d05e84e6SDmitry Torokhov [DEVTYPE_DMC_TSC10] = { 708d05e84e6SDmitry Torokhov .min_xc = 0x0, 709d05e84e6SDmitry Torokhov .max_xc = 0x03ff, 710d05e84e6SDmitry Torokhov .min_yc = 0x0, 711d05e84e6SDmitry Torokhov .max_yc = 0x03ff, 712d05e84e6SDmitry Torokhov .rept_size = 5, 713d05e84e6SDmitry Torokhov .init = dmc_tsc10_init, 714d05e84e6SDmitry Torokhov .read_data = dmc_tsc10_read_data, 715d05e84e6SDmitry Torokhov }, 716d05e84e6SDmitry Torokhov #endif 717df561fcdSOndrej Zary 718df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 719df561fcdSOndrej Zary [DEVTYPE_IRTOUCH] = { 720df561fcdSOndrej Zary .min_xc = 0x0, 721df561fcdSOndrej Zary .max_xc = 0x0fff, 722df561fcdSOndrej Zary .min_yc = 0x0, 723df561fcdSOndrej Zary .max_yc = 0x0fff, 724df561fcdSOndrej Zary .rept_size = 8, 725df561fcdSOndrej Zary .read_data = irtouch_read_data, 726df561fcdSOndrej Zary }, 727df561fcdSOndrej Zary #endif 728a14a8401SOndrej Zary 729a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 730a14a8401SOndrej Zary [DEVTYPE_IDEALTEK] = { 731a14a8401SOndrej Zary .min_xc = 0x0, 732a14a8401SOndrej Zary .max_xc = 0x0fff, 733a14a8401SOndrej Zary .min_yc = 0x0, 734a14a8401SOndrej Zary .max_yc = 0x0fff, 735a14a8401SOndrej Zary .rept_size = 8, 736a14a8401SOndrej Zary .process_pkt = usbtouch_process_multi, 737a14a8401SOndrej Zary .get_pkt_len = idealtek_get_pkt_len, 738a14a8401SOndrej Zary .read_data = idealtek_read_data, 739a14a8401SOndrej Zary }, 740a14a8401SOndrej Zary #endif 7419d5657dbSIlya Frolov 7429d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 7439d5657dbSIlya Frolov [DEVTYPE_GENERAL_TOUCH] = { 7449d5657dbSIlya Frolov .min_xc = 0x0, 7459d5657dbSIlya Frolov .max_xc = 0x0500, 7469d5657dbSIlya Frolov .min_yc = 0x0, 7479d5657dbSIlya Frolov .max_yc = 0x0500, 7489d5657dbSIlya Frolov .rept_size = 7, 7499d5657dbSIlya Frolov .read_data = general_touch_read_data, 75014e40206SJerrold Jones }, 7519d5657dbSIlya Frolov #endif 7529d5657dbSIlya Frolov 75314e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 75414e40206SJerrold Jones [DEVTYPE_GOTOP] = { 75514e40206SJerrold Jones .min_xc = 0x0, 75614e40206SJerrold Jones .max_xc = 0x03ff, 75714e40206SJerrold Jones .min_yc = 0x0, 75814e40206SJerrold Jones .max_yc = 0x03ff, 75914e40206SJerrold Jones .rept_size = 4, 76014e40206SJerrold Jones .read_data = gotop_read_data, 76114e40206SJerrold Jones }, 76214e40206SJerrold Jones #endif 763f7370699SJim Persson 764f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 765f7370699SJim Persson [DEVTYPE_JASTEC] = { 766f7370699SJim Persson .min_xc = 0x0, 767f7370699SJim Persson .max_xc = 0x0fff, 768f7370699SJim Persson .min_yc = 0x0, 769f7370699SJim Persson .max_yc = 0x0fff, 770f7370699SJim Persson .rept_size = 4, 771f7370699SJim Persson .read_data = jastec_read_data, 772f7370699SJim Persson }, 773f7370699SJim Persson #endif 774*9e3b2583SFlorian Echtler 775*9e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 776*9e3b2583SFlorian Echtler [DEVTYPE_E2I] = { 777*9e3b2583SFlorian Echtler .min_xc = 0x0, 778*9e3b2583SFlorian Echtler .max_xc = 0x7fff, 779*9e3b2583SFlorian Echtler .min_yc = 0x0, 780*9e3b2583SFlorian Echtler .max_yc = 0x7fff, 781*9e3b2583SFlorian Echtler .rept_size = 6, 782*9e3b2583SFlorian Echtler .init = e2i_init, 783*9e3b2583SFlorian Echtler .read_data = e2i_read_data, 784*9e3b2583SFlorian Echtler }, 785*9e3b2583SFlorian Echtler #endif 786d05e84e6SDmitry Torokhov }; 787d05e84e6SDmitry Torokhov 788d05e84e6SDmitry Torokhov 789d05e84e6SDmitry Torokhov /***************************************************************************** 790d05e84e6SDmitry Torokhov * Generic Part 791d05e84e6SDmitry Torokhov */ 792d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 793d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 794d05e84e6SDmitry Torokhov { 795d05e84e6SDmitry Torokhov struct usbtouch_device_info *type = usbtouch->type; 796d05e84e6SDmitry Torokhov 797d05e84e6SDmitry Torokhov if (!type->read_data(usbtouch, pkt)) 798d05e84e6SDmitry Torokhov return; 799d05e84e6SDmitry Torokhov 800d05e84e6SDmitry Torokhov input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 801d05e84e6SDmitry Torokhov 802d05e84e6SDmitry Torokhov if (swap_xy) { 803d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 804d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 805d05e84e6SDmitry Torokhov } else { 806d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 807d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 808d05e84e6SDmitry Torokhov } 809d05e84e6SDmitry Torokhov if (type->max_press) 810d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 811d05e84e6SDmitry Torokhov input_sync(usbtouch->input); 812d05e84e6SDmitry Torokhov } 813d05e84e6SDmitry Torokhov 814d05e84e6SDmitry Torokhov 815d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET 816d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 817d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 818d05e84e6SDmitry Torokhov { 819d05e84e6SDmitry Torokhov unsigned char *buffer; 820d05e84e6SDmitry Torokhov int pkt_len, pos, buf_len, tmp; 821d05e84e6SDmitry Torokhov 822d05e84e6SDmitry Torokhov /* process buffer */ 823d05e84e6SDmitry Torokhov if (unlikely(usbtouch->buf_len)) { 824d05e84e6SDmitry Torokhov /* try to get size */ 825d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 826d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 827d05e84e6SDmitry Torokhov 828d05e84e6SDmitry Torokhov /* drop? */ 829d05e84e6SDmitry Torokhov if (unlikely(!pkt_len)) 830d05e84e6SDmitry Torokhov goto out_flush_buf; 831d05e84e6SDmitry Torokhov 832d05e84e6SDmitry Torokhov /* need to append -pkt_len bytes before able to get size */ 833d05e84e6SDmitry Torokhov if (unlikely(pkt_len < 0)) { 834d05e84e6SDmitry Torokhov int append = -pkt_len; 835d05e84e6SDmitry Torokhov if (unlikely(append > len)) 836d05e84e6SDmitry Torokhov append = len; 837d05e84e6SDmitry Torokhov if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 838d05e84e6SDmitry Torokhov goto out_flush_buf; 839d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 840d05e84e6SDmitry Torokhov usbtouch->buf_len += append; 841d05e84e6SDmitry Torokhov 842d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 843d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 844d05e84e6SDmitry Torokhov if (pkt_len < 0) 845d05e84e6SDmitry Torokhov return; 846d05e84e6SDmitry Torokhov } 847d05e84e6SDmitry Torokhov 848d05e84e6SDmitry Torokhov /* append */ 849d05e84e6SDmitry Torokhov tmp = pkt_len - usbtouch->buf_len; 850d05e84e6SDmitry Torokhov if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 851d05e84e6SDmitry Torokhov goto out_flush_buf; 852d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 853d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 854d05e84e6SDmitry Torokhov 855d05e84e6SDmitry Torokhov buffer = pkt + tmp; 856d05e84e6SDmitry Torokhov buf_len = len - tmp; 857d05e84e6SDmitry Torokhov } else { 858d05e84e6SDmitry Torokhov buffer = pkt; 859d05e84e6SDmitry Torokhov buf_len = len; 860d05e84e6SDmitry Torokhov } 861d05e84e6SDmitry Torokhov 862d05e84e6SDmitry Torokhov /* loop over the received packet, process */ 863d05e84e6SDmitry Torokhov pos = 0; 864d05e84e6SDmitry Torokhov while (pos < buf_len) { 865d05e84e6SDmitry Torokhov /* get packet len */ 86662aa366dSDaniel Ritz pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 86762aa366dSDaniel Ritz buf_len - pos); 868d05e84e6SDmitry Torokhov 86962aa366dSDaniel Ritz /* unknown packet: skip one byte */ 87062aa366dSDaniel Ritz if (unlikely(!pkt_len)) { 87162aa366dSDaniel Ritz pos++; 87262aa366dSDaniel Ritz continue; 87362aa366dSDaniel Ritz } 874d05e84e6SDmitry Torokhov 875d05e84e6SDmitry Torokhov /* full packet: process */ 876d05e84e6SDmitry Torokhov if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 877d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 878d05e84e6SDmitry Torokhov } else { 879d05e84e6SDmitry Torokhov /* incomplete packet: save in buffer */ 880d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 881d05e84e6SDmitry Torokhov usbtouch->buf_len = buf_len - pos; 882d05e84e6SDmitry Torokhov return; 883d05e84e6SDmitry Torokhov } 884d05e84e6SDmitry Torokhov pos += pkt_len; 885d05e84e6SDmitry Torokhov } 886d05e84e6SDmitry Torokhov 887d05e84e6SDmitry Torokhov out_flush_buf: 888d05e84e6SDmitry Torokhov usbtouch->buf_len = 0; 889d05e84e6SDmitry Torokhov return; 890d05e84e6SDmitry Torokhov } 891d05e84e6SDmitry Torokhov #endif 892d05e84e6SDmitry Torokhov 893d05e84e6SDmitry Torokhov 894d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb) 895d05e84e6SDmitry Torokhov { 896d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = urb->context; 897d05e84e6SDmitry Torokhov int retval; 898d05e84e6SDmitry Torokhov 899d05e84e6SDmitry Torokhov switch (urb->status) { 900d05e84e6SDmitry Torokhov case 0: 901d05e84e6SDmitry Torokhov /* success */ 902d05e84e6SDmitry Torokhov break; 903d05e84e6SDmitry Torokhov case -ETIME: 904d05e84e6SDmitry Torokhov /* this urb is timing out */ 905d05e84e6SDmitry Torokhov dbg("%s - urb timed out - was the device unplugged?", 906ea3e6c59SHarvey Harrison __func__); 907d05e84e6SDmitry Torokhov return; 908d05e84e6SDmitry Torokhov case -ECONNRESET: 909d05e84e6SDmitry Torokhov case -ENOENT: 910d05e84e6SDmitry Torokhov case -ESHUTDOWN: 911d05e84e6SDmitry Torokhov /* this urb is terminated, clean up */ 912d05e84e6SDmitry Torokhov dbg("%s - urb shutting down with status: %d", 913ea3e6c59SHarvey Harrison __func__, urb->status); 914d05e84e6SDmitry Torokhov return; 915d05e84e6SDmitry Torokhov default: 916d05e84e6SDmitry Torokhov dbg("%s - nonzero urb status received: %d", 917ea3e6c59SHarvey Harrison __func__, urb->status); 918d05e84e6SDmitry Torokhov goto exit; 919d05e84e6SDmitry Torokhov } 920d05e84e6SDmitry Torokhov 921d05e84e6SDmitry Torokhov usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 922d05e84e6SDmitry Torokhov 923d05e84e6SDmitry Torokhov exit: 924d05e84e6SDmitry Torokhov retval = usb_submit_urb(urb, GFP_ATOMIC); 925d05e84e6SDmitry Torokhov if (retval) 926d05e84e6SDmitry Torokhov err("%s - usb_submit_urb failed with result: %d", 927ea3e6c59SHarvey Harrison __func__, retval); 928d05e84e6SDmitry Torokhov } 929d05e84e6SDmitry Torokhov 930d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input) 931d05e84e6SDmitry Torokhov { 932d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 933d05e84e6SDmitry Torokhov 934d05e84e6SDmitry Torokhov usbtouch->irq->dev = usbtouch->udev; 935d05e84e6SDmitry Torokhov 936d05e84e6SDmitry Torokhov if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) 937d05e84e6SDmitry Torokhov return -EIO; 938d05e84e6SDmitry Torokhov 939d05e84e6SDmitry Torokhov return 0; 940d05e84e6SDmitry Torokhov } 941d05e84e6SDmitry Torokhov 942d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input) 943d05e84e6SDmitry Torokhov { 944d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 945d05e84e6SDmitry Torokhov 946d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 947d05e84e6SDmitry Torokhov } 948d05e84e6SDmitry Torokhov 949d05e84e6SDmitry Torokhov 950d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev, 951d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch) 952d05e84e6SDmitry Torokhov { 953d05e84e6SDmitry Torokhov usb_buffer_free(udev, usbtouch->type->rept_size, 954d05e84e6SDmitry Torokhov usbtouch->data, usbtouch->data_dma); 955d05e84e6SDmitry Torokhov kfree(usbtouch->buffer); 956d05e84e6SDmitry Torokhov } 957d05e84e6SDmitry Torokhov 958d05e84e6SDmitry Torokhov 959d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf, 960d05e84e6SDmitry Torokhov const struct usb_device_id *id) 961d05e84e6SDmitry Torokhov { 962d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch; 963d05e84e6SDmitry Torokhov struct input_dev *input_dev; 964d05e84e6SDmitry Torokhov struct usb_host_interface *interface; 965d05e84e6SDmitry Torokhov struct usb_endpoint_descriptor *endpoint; 966d05e84e6SDmitry Torokhov struct usb_device *udev = interface_to_usbdev(intf); 967d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 968d05e84e6SDmitry Torokhov int err = -ENOMEM; 969d05e84e6SDmitry Torokhov 970ec42d448SDaniel Ritz /* some devices are ignored */ 971ec42d448SDaniel Ritz if (id->driver_info == DEVTYPE_IGNORE) 972ec42d448SDaniel Ritz return -ENODEV; 973ec42d448SDaniel Ritz 974d05e84e6SDmitry Torokhov interface = intf->cur_altsetting; 975d05e84e6SDmitry Torokhov endpoint = &interface->endpoint[0].desc; 976d05e84e6SDmitry Torokhov 977d05e84e6SDmitry Torokhov usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 978d05e84e6SDmitry Torokhov input_dev = input_allocate_device(); 979d05e84e6SDmitry Torokhov if (!usbtouch || !input_dev) 980d05e84e6SDmitry Torokhov goto out_free; 981d05e84e6SDmitry Torokhov 982d05e84e6SDmitry Torokhov type = &usbtouch_dev_info[id->driver_info]; 983d05e84e6SDmitry Torokhov usbtouch->type = type; 984d05e84e6SDmitry Torokhov if (!type->process_pkt) 985d05e84e6SDmitry Torokhov type->process_pkt = usbtouch_process_pkt; 986d05e84e6SDmitry Torokhov 987d05e84e6SDmitry Torokhov usbtouch->data = usb_buffer_alloc(udev, type->rept_size, 988d05e84e6SDmitry Torokhov GFP_KERNEL, &usbtouch->data_dma); 989d05e84e6SDmitry Torokhov if (!usbtouch->data) 990d05e84e6SDmitry Torokhov goto out_free; 991d05e84e6SDmitry Torokhov 99262aa366dSDaniel Ritz if (type->get_pkt_len) { 993d05e84e6SDmitry Torokhov usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 994d05e84e6SDmitry Torokhov if (!usbtouch->buffer) 995d05e84e6SDmitry Torokhov goto out_free_buffers; 996d05e84e6SDmitry Torokhov } 997d05e84e6SDmitry Torokhov 998d05e84e6SDmitry Torokhov usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 999d05e84e6SDmitry Torokhov if (!usbtouch->irq) { 1000ea3e6c59SHarvey Harrison dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); 1001d05e84e6SDmitry Torokhov goto out_free_buffers; 1002d05e84e6SDmitry Torokhov } 1003d05e84e6SDmitry Torokhov 1004d05e84e6SDmitry Torokhov usbtouch->udev = udev; 1005d05e84e6SDmitry Torokhov usbtouch->input = input_dev; 1006d05e84e6SDmitry Torokhov 1007d05e84e6SDmitry Torokhov if (udev->manufacturer) 1008d05e84e6SDmitry Torokhov strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 1009d05e84e6SDmitry Torokhov 1010d05e84e6SDmitry Torokhov if (udev->product) { 1011d05e84e6SDmitry Torokhov if (udev->manufacturer) 1012d05e84e6SDmitry Torokhov strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 1013d05e84e6SDmitry Torokhov strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 1014d05e84e6SDmitry Torokhov } 1015d05e84e6SDmitry Torokhov 1016d05e84e6SDmitry Torokhov if (!strlen(usbtouch->name)) 1017d05e84e6SDmitry Torokhov snprintf(usbtouch->name, sizeof(usbtouch->name), 1018d05e84e6SDmitry Torokhov "USB Touchscreen %04x:%04x", 1019d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idVendor), 1020d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idProduct)); 1021d05e84e6SDmitry Torokhov 1022d05e84e6SDmitry Torokhov usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 10237b6dff98SVladimir Shebordaev strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 1024d05e84e6SDmitry Torokhov 1025d05e84e6SDmitry Torokhov input_dev->name = usbtouch->name; 1026d05e84e6SDmitry Torokhov input_dev->phys = usbtouch->phys; 1027d05e84e6SDmitry Torokhov usb_to_input_id(udev, &input_dev->id); 1028d05e84e6SDmitry Torokhov input_dev->dev.parent = &intf->dev; 1029d05e84e6SDmitry Torokhov 1030d05e84e6SDmitry Torokhov input_set_drvdata(input_dev, usbtouch); 1031d05e84e6SDmitry Torokhov 1032d05e84e6SDmitry Torokhov input_dev->open = usbtouch_open; 1033d05e84e6SDmitry Torokhov input_dev->close = usbtouch_close; 1034d05e84e6SDmitry Torokhov 10357b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 10367b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1037d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 1038d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 1039d05e84e6SDmitry Torokhov if (type->max_press) 1040d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 1041d05e84e6SDmitry Torokhov type->max_press, 0, 0); 1042d05e84e6SDmitry Torokhov 1043d05e84e6SDmitry Torokhov usb_fill_int_urb(usbtouch->irq, usbtouch->udev, 1044d05e84e6SDmitry Torokhov usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), 1045d05e84e6SDmitry Torokhov usbtouch->data, type->rept_size, 1046d05e84e6SDmitry Torokhov usbtouch_irq, usbtouch, endpoint->bInterval); 1047d05e84e6SDmitry Torokhov 1048d05e84e6SDmitry Torokhov usbtouch->irq->dev = usbtouch->udev; 1049d05e84e6SDmitry Torokhov usbtouch->irq->transfer_dma = usbtouch->data_dma; 1050d05e84e6SDmitry Torokhov usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1051d05e84e6SDmitry Torokhov 1052d05e84e6SDmitry Torokhov /* device specific init */ 1053d05e84e6SDmitry Torokhov if (type->init) { 1054d05e84e6SDmitry Torokhov err = type->init(usbtouch); 1055d05e84e6SDmitry Torokhov if (err) { 1056ea3e6c59SHarvey Harrison dbg("%s - type->init() failed, err: %d", __func__, err); 1057d05e84e6SDmitry Torokhov goto out_free_buffers; 1058d05e84e6SDmitry Torokhov } 1059d05e84e6SDmitry Torokhov } 1060d05e84e6SDmitry Torokhov 1061d05e84e6SDmitry Torokhov err = input_register_device(usbtouch->input); 1062d05e84e6SDmitry Torokhov if (err) { 1063ea3e6c59SHarvey Harrison dbg("%s - input_register_device failed, err: %d", __func__, err); 1064d05e84e6SDmitry Torokhov goto out_free_buffers; 1065d05e84e6SDmitry Torokhov } 1066d05e84e6SDmitry Torokhov 1067d05e84e6SDmitry Torokhov usb_set_intfdata(intf, usbtouch); 1068d05e84e6SDmitry Torokhov 1069d05e84e6SDmitry Torokhov return 0; 1070d05e84e6SDmitry Torokhov 1071d05e84e6SDmitry Torokhov out_free_buffers: 1072d05e84e6SDmitry Torokhov usbtouch_free_buffers(udev, usbtouch); 1073d05e84e6SDmitry Torokhov out_free: 1074d05e84e6SDmitry Torokhov input_free_device(input_dev); 1075d05e84e6SDmitry Torokhov kfree(usbtouch); 1076d05e84e6SDmitry Torokhov return err; 1077d05e84e6SDmitry Torokhov } 1078d05e84e6SDmitry Torokhov 1079d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf) 1080d05e84e6SDmitry Torokhov { 1081d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1082d05e84e6SDmitry Torokhov 1083ea3e6c59SHarvey Harrison dbg("%s - called", __func__); 1084d05e84e6SDmitry Torokhov 1085d05e84e6SDmitry Torokhov if (!usbtouch) 1086d05e84e6SDmitry Torokhov return; 1087d05e84e6SDmitry Torokhov 1088ea3e6c59SHarvey Harrison dbg("%s - usbtouch is initialized, cleaning up", __func__); 1089d05e84e6SDmitry Torokhov usb_set_intfdata(intf, NULL); 1090d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 1091d05e84e6SDmitry Torokhov input_unregister_device(usbtouch->input); 1092d05e84e6SDmitry Torokhov usb_free_urb(usbtouch->irq); 1093d05e84e6SDmitry Torokhov usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 1094d05e84e6SDmitry Torokhov kfree(usbtouch); 1095d05e84e6SDmitry Torokhov } 1096d05e84e6SDmitry Torokhov 1097d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices); 1098d05e84e6SDmitry Torokhov 1099d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = { 1100d05e84e6SDmitry Torokhov .name = "usbtouchscreen", 1101d05e84e6SDmitry Torokhov .probe = usbtouch_probe, 1102d05e84e6SDmitry Torokhov .disconnect = usbtouch_disconnect, 1103d05e84e6SDmitry Torokhov .id_table = usbtouch_devices, 1104d05e84e6SDmitry Torokhov }; 1105d05e84e6SDmitry Torokhov 1106d05e84e6SDmitry Torokhov static int __init usbtouch_init(void) 1107d05e84e6SDmitry Torokhov { 1108d05e84e6SDmitry Torokhov return usb_register(&usbtouch_driver); 1109d05e84e6SDmitry Torokhov } 1110d05e84e6SDmitry Torokhov 1111d05e84e6SDmitry Torokhov static void __exit usbtouch_cleanup(void) 1112d05e84e6SDmitry Torokhov { 1113d05e84e6SDmitry Torokhov usb_deregister(&usbtouch_driver); 1114d05e84e6SDmitry Torokhov } 1115d05e84e6SDmitry Torokhov 1116d05e84e6SDmitry Torokhov module_init(usbtouch_init); 1117d05e84e6SDmitry Torokhov module_exit(usbtouch_cleanup); 1118d05e84e6SDmitry Torokhov 1119d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR); 1120d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC); 1121d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL"); 1122d05e84e6SDmitry Torokhov 1123d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb"); 1124d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch"); 1125d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb"); 1126