at v2.6.14 300 lines 8.2 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#include <linux/usb_input.h> 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 usb_to_input_id(udev, &touchkit->input.id); 206 touchkit->input.dev = &intf->dev; 207 208 touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 209 touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); 210 touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 211 212 /* Used to Scale Compensated Data */ 213 touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; 214 touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; 215 touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; 216 touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; 217 touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; 218 touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; 219 touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; 220 touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; 221 222 if (udev->manufacturer) 223 strcat(touchkit->name, udev->manufacturer); 224 if (udev->product) 225 sprintf(touchkit->name, "%s %s", touchkit->name, udev->product); 226 227 if (!strlen(touchkit->name)) 228 sprintf(touchkit->name, "USB Touchscreen %04x:%04x", 229 touchkit->input.id.vendor, touchkit->input.id.product); 230 231 touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); 232 if (!touchkit->irq) { 233 dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); 234 ret = -ENOMEM; 235 goto out_free_buffers; 236 } 237 238 usb_fill_int_urb(touchkit->irq, touchkit->udev, 239 usb_rcvintpipe(touchkit->udev, 0x81), 240 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, 241 touchkit_irq, touchkit, endpoint->bInterval); 242 243 input_register_device(&touchkit->input); 244 245 printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); 246 usb_set_intfdata(intf, touchkit); 247 248 return 0; 249 250out_free_buffers: 251 touchkit_free_buffers(udev, touchkit); 252out_free: 253 kfree(touchkit); 254 return ret; 255} 256 257static void touchkit_disconnect(struct usb_interface *intf) 258{ 259 struct touchkit_usb *touchkit = usb_get_intfdata(intf); 260 261 dbg("%s - called", __FUNCTION__); 262 263 if (!touchkit) 264 return; 265 266 dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); 267 usb_set_intfdata(intf, NULL); 268 input_unregister_device(&touchkit->input); 269 usb_kill_urb(touchkit->irq); 270 usb_free_urb(touchkit->irq); 271 touchkit_free_buffers(interface_to_usbdev(intf), touchkit); 272 kfree(touchkit); 273} 274 275MODULE_DEVICE_TABLE(usb, touchkit_devices); 276 277static struct usb_driver touchkit_driver = { 278 .owner = THIS_MODULE, 279 .name = "touchkitusb", 280 .probe = touchkit_probe, 281 .disconnect = touchkit_disconnect, 282 .id_table = touchkit_devices, 283}; 284 285static int __init touchkit_init(void) 286{ 287 return usb_register(&touchkit_driver); 288} 289 290static void __exit touchkit_cleanup(void) 291{ 292 usb_deregister(&touchkit_driver); 293} 294 295module_init(touchkit_init); 296module_exit(touchkit_cleanup); 297 298MODULE_AUTHOR(DRIVER_AUTHOR); 299MODULE_DESCRIPTION(DRIVER_DESC); 300MODULE_LICENSE("GPL");