Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12 310 lines 8.4 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 int open; 73 char name[128]; 74 char phys[64]; 75}; 76 77static struct usb_device_id touchkit_devices[] = { 78 {USB_DEVICE(0x3823, 0x0001)}, 79 {USB_DEVICE(0x0eef, 0x0001)}, 80 {} 81}; 82 83static void touchkit_irq(struct urb *urb, struct pt_regs *regs) 84{ 85 struct touchkit_usb *touchkit = urb->context; 86 int retval; 87 int x, y; 88 89 switch (urb->status) { 90 case 0: 91 /* success */ 92 break; 93 case -ETIMEDOUT: 94 /* this urb is timing out */ 95 dbg("%s - urb timed out - was the device unplugged?", 96 __FUNCTION__); 97 return; 98 case -ECONNRESET: 99 case -ENOENT: 100 case -ESHUTDOWN: 101 /* this urb is terminated, clean up */ 102 dbg("%s - urb shutting down with status: %d", 103 __FUNCTION__, urb->status); 104 return; 105 default: 106 dbg("%s - nonzero urb status received: %d", 107 __FUNCTION__, urb->status); 108 goto exit; 109 } 110 111 if (swap_xy) { 112 y = TOUCHKIT_GET_X(touchkit->data); 113 x = TOUCHKIT_GET_Y(touchkit->data); 114 } else { 115 x = TOUCHKIT_GET_X(touchkit->data); 116 y = TOUCHKIT_GET_Y(touchkit->data); 117 } 118 119 input_regs(&touchkit->input, regs); 120 input_report_key(&touchkit->input, BTN_TOUCH, 121 TOUCHKIT_GET_TOUCHED(touchkit->data)); 122 input_report_abs(&touchkit->input, ABS_X, x); 123 input_report_abs(&touchkit->input, ABS_Y, y); 124 input_sync(&touchkit->input); 125 126exit: 127 retval = usb_submit_urb(urb, GFP_ATOMIC); 128 if (retval) 129 err("%s - usb_submit_urb failed with result: %d", 130 __FUNCTION__, retval); 131} 132 133static int touchkit_open(struct input_dev *input) 134{ 135 struct touchkit_usb *touchkit = input->private; 136 137 if (touchkit->open++) 138 return 0; 139 140 touchkit->irq->dev = touchkit->udev; 141 142 if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { 143 touchkit->open--; 144 return -EIO; 145 } 146 147 return 0; 148} 149 150static void touchkit_close(struct input_dev *input) 151{ 152 struct touchkit_usb *touchkit = input->private; 153 154 if (!--touchkit->open) 155 usb_kill_urb(touchkit->irq); 156} 157 158static int touchkit_alloc_buffers(struct usb_device *udev, 159 struct touchkit_usb *touchkit) 160{ 161 touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, 162 SLAB_ATOMIC, &touchkit->data_dma); 163 164 if (!touchkit->data) 165 return -1; 166 167 return 0; 168} 169 170static void touchkit_free_buffers(struct usb_device *udev, 171 struct touchkit_usb *touchkit) 172{ 173 if (touchkit->data) 174 usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, 175 touchkit->data, touchkit->data_dma); 176} 177 178static int touchkit_probe(struct usb_interface *intf, 179 const struct usb_device_id *id) 180{ 181 int ret; 182 struct touchkit_usb *touchkit; 183 struct usb_host_interface *interface; 184 struct usb_endpoint_descriptor *endpoint; 185 struct usb_device *udev = interface_to_usbdev(intf); 186 char path[64]; 187 188 interface = intf->cur_altsetting; 189 endpoint = &interface->endpoint[0].desc; 190 191 touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL); 192 if (!touchkit) 193 return -ENOMEM; 194 195 memset(touchkit, 0, sizeof(struct touchkit_usb)); 196 touchkit->udev = udev; 197 198 if (touchkit_alloc_buffers(udev, touchkit)) { 199 ret = -ENOMEM; 200 goto out_free; 201 } 202 203 touchkit->input.private = touchkit; 204 touchkit->input.open = touchkit_open; 205 touchkit->input.close = touchkit_close; 206 207 usb_make_path(udev, path, 64); 208 sprintf(touchkit->phys, "%s/input0", path); 209 210 touchkit->input.name = touchkit->name; 211 touchkit->input.phys = touchkit->phys; 212 touchkit->input.id.bustype = BUS_USB; 213 touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); 214 touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct); 215 touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); 216 touchkit->input.dev = &intf->dev; 217 218 touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 219 touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); 220 touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 221 222 /* Used to Scale Compensated Data */ 223 touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; 224 touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; 225 touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; 226 touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; 227 touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; 228 touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; 229 touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; 230 touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; 231 232 if (udev->manufacturer) 233 strcat(touchkit->name, udev->manufacturer); 234 if (udev->product) 235 sprintf(touchkit->name, "%s %s", touchkit->name, udev->product); 236 237 if (!strlen(touchkit->name)) 238 sprintf(touchkit->name, "USB Touchscreen %04x:%04x", 239 touchkit->input.id.vendor, touchkit->input.id.product); 240 241 touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); 242 if (!touchkit->irq) { 243 dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); 244 ret = -ENOMEM; 245 goto out_free_buffers; 246 } 247 248 usb_fill_int_urb(touchkit->irq, touchkit->udev, 249 usb_rcvintpipe(touchkit->udev, 0x81), 250 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, 251 touchkit_irq, touchkit, endpoint->bInterval); 252 253 input_register_device(&touchkit->input); 254 255 printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); 256 usb_set_intfdata(intf, touchkit); 257 258 return 0; 259 260out_free_buffers: 261 touchkit_free_buffers(udev, touchkit); 262out_free: 263 kfree(touchkit); 264 return ret; 265} 266 267static void touchkit_disconnect(struct usb_interface *intf) 268{ 269 struct touchkit_usb *touchkit = usb_get_intfdata(intf); 270 271 dbg("%s - called", __FUNCTION__); 272 273 if (!touchkit) 274 return; 275 276 dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); 277 usb_set_intfdata(intf, NULL); 278 input_unregister_device(&touchkit->input); 279 usb_kill_urb(touchkit->irq); 280 usb_free_urb(touchkit->irq); 281 touchkit_free_buffers(interface_to_usbdev(intf), touchkit); 282 kfree(touchkit); 283} 284 285MODULE_DEVICE_TABLE(usb, touchkit_devices); 286 287static struct usb_driver touchkit_driver = { 288 .owner = THIS_MODULE, 289 .name = "touchkitusb", 290 .probe = touchkit_probe, 291 .disconnect = touchkit_disconnect, 292 .id_table = touchkit_devices, 293}; 294 295static int __init touchkit_init(void) 296{ 297 return usb_register(&touchkit_driver); 298} 299 300static void __exit touchkit_cleanup(void) 301{ 302 usb_deregister(&touchkit_driver); 303} 304 305module_init(touchkit_init); 306module_exit(touchkit_cleanup); 307 308MODULE_AUTHOR(DRIVER_AUTHOR); 309MODULE_DESCRIPTION(DRIVER_DESC); 310MODULE_LICENSE("GPL");