at v2.6.13-rc2 303 lines 8.3 kB view raw
1/****************************************************************************** 2 * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens 3 * 4 * Copyright (C) 2004 by Daniel Ritz 5 * Copyright (C) by Todd E. Johnson (mtouchusb.c) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 * Based upon mtouchusb.c 22 * 23 *****************************************************************************/ 24 25//#define DEBUG 26 27#include <linux/config.h> 28#include <linux/kernel.h> 29#include <linux/slab.h> 30#include <linux/input.h> 31#include <linux/module.h> 32#include <linux/init.h> 33 34#if !defined(DEBUG) && defined(CONFIG_USB_DEBUG) 35#define DEBUG 36#endif 37#include <linux/usb.h> 38 39 40#define TOUCHKIT_MIN_XC 0x0 41#define TOUCHKIT_MAX_XC 0x07ff 42#define TOUCHKIT_XC_FUZZ 0x0 43#define TOUCHKIT_XC_FLAT 0x0 44#define TOUCHKIT_MIN_YC 0x0 45#define TOUCHKIT_MAX_YC 0x07ff 46#define TOUCHKIT_YC_FUZZ 0x0 47#define TOUCHKIT_YC_FLAT 0x0 48#define TOUCHKIT_REPORT_DATA_SIZE 8 49 50#define TOUCHKIT_DOWN 0x01 51#define TOUCHKIT_POINT_TOUCH 0x81 52#define TOUCHKIT_POINT_NOTOUCH 0x80 53 54#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0) 55#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4]) 56#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2]) 57 58#define DRIVER_VERSION "v0.1" 59#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 60#define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" 61 62static int swap_xy; 63module_param(swap_xy, bool, 0644); 64MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 65 66struct touchkit_usb { 67 unsigned char *data; 68 dma_addr_t data_dma; 69 struct urb *irq; 70 struct usb_device *udev; 71 struct input_dev input; 72 char name[128]; 73 char phys[64]; 74}; 75 76static struct usb_device_id touchkit_devices[] = { 77 {USB_DEVICE(0x3823, 0x0001)}, 78 {USB_DEVICE(0x0eef, 0x0001)}, 79 {} 80}; 81 82static void touchkit_irq(struct urb *urb, struct pt_regs *regs) 83{ 84 struct touchkit_usb *touchkit = urb->context; 85 int retval; 86 int x, y; 87 88 switch (urb->status) { 89 case 0: 90 /* success */ 91 break; 92 case -ETIMEDOUT: 93 /* this urb is timing out */ 94 dbg("%s - urb timed out - was the device unplugged?", 95 __FUNCTION__); 96 return; 97 case -ECONNRESET: 98 case -ENOENT: 99 case -ESHUTDOWN: 100 /* this urb is terminated, clean up */ 101 dbg("%s - urb shutting down with status: %d", 102 __FUNCTION__, urb->status); 103 return; 104 default: 105 dbg("%s - nonzero urb status received: %d", 106 __FUNCTION__, urb->status); 107 goto exit; 108 } 109 110 if (swap_xy) { 111 y = TOUCHKIT_GET_X(touchkit->data); 112 x = TOUCHKIT_GET_Y(touchkit->data); 113 } else { 114 x = TOUCHKIT_GET_X(touchkit->data); 115 y = TOUCHKIT_GET_Y(touchkit->data); 116 } 117 118 input_regs(&touchkit->input, regs); 119 input_report_key(&touchkit->input, BTN_TOUCH, 120 TOUCHKIT_GET_TOUCHED(touchkit->data)); 121 input_report_abs(&touchkit->input, ABS_X, x); 122 input_report_abs(&touchkit->input, ABS_Y, y); 123 input_sync(&touchkit->input); 124 125exit: 126 retval = usb_submit_urb(urb, GFP_ATOMIC); 127 if (retval) 128 err("%s - usb_submit_urb failed with result: %d", 129 __FUNCTION__, retval); 130} 131 132static int touchkit_open(struct input_dev *input) 133{ 134 struct touchkit_usb *touchkit = input->private; 135 136 touchkit->irq->dev = touchkit->udev; 137 138 if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) 139 return -EIO; 140 141 return 0; 142} 143 144static void touchkit_close(struct input_dev *input) 145{ 146 struct touchkit_usb *touchkit = input->private; 147 148 usb_kill_urb(touchkit->irq); 149} 150 151static int touchkit_alloc_buffers(struct usb_device *udev, 152 struct touchkit_usb *touchkit) 153{ 154 touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, 155 SLAB_ATOMIC, &touchkit->data_dma); 156 157 if (!touchkit->data) 158 return -1; 159 160 return 0; 161} 162 163static void touchkit_free_buffers(struct usb_device *udev, 164 struct touchkit_usb *touchkit) 165{ 166 if (touchkit->data) 167 usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, 168 touchkit->data, touchkit->data_dma); 169} 170 171static int touchkit_probe(struct usb_interface *intf, 172 const struct usb_device_id *id) 173{ 174 int ret; 175 struct touchkit_usb *touchkit; 176 struct usb_host_interface *interface; 177 struct usb_endpoint_descriptor *endpoint; 178 struct usb_device *udev = interface_to_usbdev(intf); 179 char path[64]; 180 181 interface = intf->cur_altsetting; 182 endpoint = &interface->endpoint[0].desc; 183 184 touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL); 185 if (!touchkit) 186 return -ENOMEM; 187 188 memset(touchkit, 0, sizeof(struct touchkit_usb)); 189 touchkit->udev = udev; 190 191 if (touchkit_alloc_buffers(udev, touchkit)) { 192 ret = -ENOMEM; 193 goto out_free; 194 } 195 196 touchkit->input.private = touchkit; 197 touchkit->input.open = touchkit_open; 198 touchkit->input.close = touchkit_close; 199 200 usb_make_path(udev, path, 64); 201 sprintf(touchkit->phys, "%s/input0", path); 202 203 touchkit->input.name = touchkit->name; 204 touchkit->input.phys = touchkit->phys; 205 touchkit->input.id.bustype = BUS_USB; 206 touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); 207 touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct); 208 touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); 209 touchkit->input.dev = &intf->dev; 210 211 touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 212 touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); 213 touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 214 215 /* Used to Scale Compensated Data */ 216 touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; 217 touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; 218 touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; 219 touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; 220 touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; 221 touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; 222 touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; 223 touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; 224 225 if (udev->manufacturer) 226 strcat(touchkit->name, udev->manufacturer); 227 if (udev->product) 228 sprintf(touchkit->name, "%s %s", touchkit->name, udev->product); 229 230 if (!strlen(touchkit->name)) 231 sprintf(touchkit->name, "USB Touchscreen %04x:%04x", 232 touchkit->input.id.vendor, touchkit->input.id.product); 233 234 touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); 235 if (!touchkit->irq) { 236 dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); 237 ret = -ENOMEM; 238 goto out_free_buffers; 239 } 240 241 usb_fill_int_urb(touchkit->irq, touchkit->udev, 242 usb_rcvintpipe(touchkit->udev, 0x81), 243 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, 244 touchkit_irq, touchkit, endpoint->bInterval); 245 246 input_register_device(&touchkit->input); 247 248 printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); 249 usb_set_intfdata(intf, touchkit); 250 251 return 0; 252 253out_free_buffers: 254 touchkit_free_buffers(udev, touchkit); 255out_free: 256 kfree(touchkit); 257 return ret; 258} 259 260static void touchkit_disconnect(struct usb_interface *intf) 261{ 262 struct touchkit_usb *touchkit = usb_get_intfdata(intf); 263 264 dbg("%s - called", __FUNCTION__); 265 266 if (!touchkit) 267 return; 268 269 dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); 270 usb_set_intfdata(intf, NULL); 271 input_unregister_device(&touchkit->input); 272 usb_kill_urb(touchkit->irq); 273 usb_free_urb(touchkit->irq); 274 touchkit_free_buffers(interface_to_usbdev(intf), touchkit); 275 kfree(touchkit); 276} 277 278MODULE_DEVICE_TABLE(usb, touchkit_devices); 279 280static struct usb_driver touchkit_driver = { 281 .owner = THIS_MODULE, 282 .name = "touchkitusb", 283 .probe = touchkit_probe, 284 .disconnect = touchkit_disconnect, 285 .id_table = touchkit_devices, 286}; 287 288static int __init touchkit_init(void) 289{ 290 return usb_register(&touchkit_driver); 291} 292 293static void __exit touchkit_cleanup(void) 294{ 295 usb_deregister(&touchkit_driver); 296} 297 298module_init(touchkit_init); 299module_exit(touchkit_cleanup); 300 301MODULE_AUTHOR(DRIVER_AUTHOR); 302MODULE_DESCRIPTION(DRIVER_DESC); 303MODULE_LICENSE("GPL");