Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 398 lines 10 kB view raw
1/****************************************************************************** 2 * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens 3 * 4 * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch> 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#include <linux/usb.h> 34#include <linux/usb_input.h> 35 36#define TOUCHKIT_MIN_XC 0x0 37#define TOUCHKIT_MAX_XC 0x07ff 38#define TOUCHKIT_XC_FUZZ 0x0 39#define TOUCHKIT_XC_FLAT 0x0 40#define TOUCHKIT_MIN_YC 0x0 41#define TOUCHKIT_MAX_YC 0x07ff 42#define TOUCHKIT_YC_FUZZ 0x0 43#define TOUCHKIT_YC_FLAT 0x0 44#define TOUCHKIT_REPORT_DATA_SIZE 16 45 46#define TOUCHKIT_DOWN 0x01 47 48#define TOUCHKIT_PKT_TYPE_MASK 0xFE 49#define TOUCHKIT_PKT_TYPE_REPT 0x80 50#define TOUCHKIT_PKT_TYPE_DIAG 0x0A 51 52#define DRIVER_VERSION "v0.1" 53#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 54#define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" 55 56static int swap_xy; 57module_param(swap_xy, bool, 0644); 58MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 59 60struct touchkit_usb { 61 unsigned char *data; 62 dma_addr_t data_dma; 63 char buffer[TOUCHKIT_REPORT_DATA_SIZE]; 64 int buf_len; 65 struct urb *irq; 66 struct usb_device *udev; 67 struct input_dev *input; 68 char name[128]; 69 char phys[64]; 70}; 71 72static struct usb_device_id touchkit_devices[] = { 73 {USB_DEVICE(0x3823, 0x0001)}, 74 {USB_DEVICE(0x0123, 0x0001)}, 75 {USB_DEVICE(0x0eef, 0x0001)}, 76 {USB_DEVICE(0x0eef, 0x0002)}, 77 {} 78}; 79 80/* helpers to read the data */ 81static inline int touchkit_get_touched(char *data) 82{ 83 return (data[0] & TOUCHKIT_DOWN) ? 1 : 0; 84} 85 86static inline int touchkit_get_x(char *data) 87{ 88 return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F); 89} 90 91static inline int touchkit_get_y(char *data) 92{ 93 return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F); 94} 95 96 97/* processes one input packet. */ 98static void touchkit_process_pkt(struct touchkit_usb *touchkit, 99 struct pt_regs *regs, char *pkt) 100{ 101 int x, y; 102 103 /* only process report packets */ 104 if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT) 105 return; 106 107 if (swap_xy) { 108 y = touchkit_get_x(pkt); 109 x = touchkit_get_y(pkt); 110 } else { 111 x = touchkit_get_x(pkt); 112 y = touchkit_get_y(pkt); 113 } 114 115 input_regs(touchkit->input, regs); 116 input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt)); 117 input_report_abs(touchkit->input, ABS_X, x); 118 input_report_abs(touchkit->input, ABS_Y, y); 119 input_sync(touchkit->input); 120} 121 122 123static int touchkit_get_pkt_len(char *buf) 124{ 125 switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) { 126 case TOUCHKIT_PKT_TYPE_REPT: 127 return 5; 128 129 case TOUCHKIT_PKT_TYPE_DIAG: 130 return buf[1] + 2; 131 } 132 133 return 0; 134} 135 136static void touchkit_process(struct touchkit_usb *touchkit, int len, 137 struct pt_regs *regs) 138{ 139 char *buffer; 140 int pkt_len, buf_len, pos; 141 142 /* if the buffer contains data, append */ 143 if (unlikely(touchkit->buf_len)) { 144 int tmp; 145 146 /* if only 1 byte in buffer, add another one to get length */ 147 if (touchkit->buf_len == 1) 148 touchkit->buffer[1] = touchkit->data[0]; 149 150 pkt_len = touchkit_get_pkt_len(touchkit->buffer); 151 152 /* unknown packet: drop everything */ 153 if (!pkt_len) 154 return; 155 156 /* append, process */ 157 tmp = pkt_len - touchkit->buf_len; 158 memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp); 159 touchkit_process_pkt(touchkit, regs, touchkit->buffer); 160 161 buffer = touchkit->data + tmp; 162 buf_len = len - tmp; 163 } else { 164 buffer = touchkit->data; 165 buf_len = len; 166 } 167 168 /* only one byte left in buffer */ 169 if (unlikely(buf_len == 1)) { 170 touchkit->buffer[0] = buffer[0]; 171 touchkit->buf_len = 1; 172 return; 173 } 174 175 /* loop over the buffer */ 176 pos = 0; 177 while (pos < buf_len) { 178 /* get packet len */ 179 pkt_len = touchkit_get_pkt_len(buffer + pos); 180 181 /* unknown packet: drop everything */ 182 if (unlikely(!pkt_len)) 183 return; 184 185 /* full packet: process */ 186 if (likely(pkt_len <= buf_len)) { 187 touchkit_process_pkt(touchkit, regs, buffer + pos); 188 } else { 189 /* incomplete packet: save in buffer */ 190 memcpy(touchkit->buffer, buffer + pos, buf_len - pos); 191 touchkit->buf_len = buf_len - pos; 192 } 193 pos += pkt_len; 194 } 195} 196 197 198static void touchkit_irq(struct urb *urb, struct pt_regs *regs) 199{ 200 struct touchkit_usb *touchkit = urb->context; 201 int retval; 202 203 switch (urb->status) { 204 case 0: 205 /* success */ 206 break; 207 case -ETIMEDOUT: 208 /* this urb is timing out */ 209 dbg("%s - urb timed out - was the device unplugged?", 210 __FUNCTION__); 211 return; 212 case -ECONNRESET: 213 case -ENOENT: 214 case -ESHUTDOWN: 215 /* this urb is terminated, clean up */ 216 dbg("%s - urb shutting down with status: %d", 217 __FUNCTION__, urb->status); 218 return; 219 default: 220 dbg("%s - nonzero urb status received: %d", 221 __FUNCTION__, urb->status); 222 goto exit; 223 } 224 225 touchkit_process(touchkit, urb->actual_length, regs); 226 227exit: 228 retval = usb_submit_urb(urb, GFP_ATOMIC); 229 if (retval) 230 err("%s - usb_submit_urb failed with result: %d", 231 __FUNCTION__, retval); 232} 233 234static int touchkit_open(struct input_dev *input) 235{ 236 struct touchkit_usb *touchkit = input->private; 237 238 touchkit->irq->dev = touchkit->udev; 239 240 if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) 241 return -EIO; 242 243 return 0; 244} 245 246static void touchkit_close(struct input_dev *input) 247{ 248 struct touchkit_usb *touchkit = input->private; 249 250 usb_kill_urb(touchkit->irq); 251} 252 253static int touchkit_alloc_buffers(struct usb_device *udev, 254 struct touchkit_usb *touchkit) 255{ 256 touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, 257 SLAB_ATOMIC, &touchkit->data_dma); 258 259 if (!touchkit->data) 260 return -1; 261 262 return 0; 263} 264 265static void touchkit_free_buffers(struct usb_device *udev, 266 struct touchkit_usb *touchkit) 267{ 268 if (touchkit->data) 269 usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, 270 touchkit->data, touchkit->data_dma); 271} 272 273static int touchkit_probe(struct usb_interface *intf, 274 const struct usb_device_id *id) 275{ 276 struct touchkit_usb *touchkit; 277 struct input_dev *input_dev; 278 struct usb_host_interface *interface; 279 struct usb_endpoint_descriptor *endpoint; 280 struct usb_device *udev = interface_to_usbdev(intf); 281 282 interface = intf->cur_altsetting; 283 endpoint = &interface->endpoint[0].desc; 284 285 touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL); 286 input_dev = input_allocate_device(); 287 if (!touchkit || !input_dev) 288 goto out_free; 289 290 if (touchkit_alloc_buffers(udev, touchkit)) 291 goto out_free; 292 293 touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); 294 if (!touchkit->irq) { 295 dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); 296 goto out_free_buffers; 297 } 298 299 touchkit->udev = udev; 300 touchkit->input = input_dev; 301 302 if (udev->manufacturer) 303 strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name)); 304 305 if (udev->product) { 306 if (udev->manufacturer) 307 strlcat(touchkit->name, " ", sizeof(touchkit->name)); 308 strlcat(touchkit->name, udev->product, sizeof(touchkit->name)); 309 } 310 311 if (!strlen(touchkit->name)) 312 snprintf(touchkit->name, sizeof(touchkit->name), 313 "USB Touchscreen %04x:%04x", 314 le16_to_cpu(udev->descriptor.idVendor), 315 le16_to_cpu(udev->descriptor.idProduct)); 316 317 usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys)); 318 strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys)); 319 320 input_dev->name = touchkit->name; 321 input_dev->phys = touchkit->phys; 322 usb_to_input_id(udev, &input_dev->id); 323 input_dev->cdev.dev = &intf->dev; 324 input_dev->private = touchkit; 325 input_dev->open = touchkit_open; 326 input_dev->close = touchkit_close; 327 328 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 329 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 330 input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC, 331 TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT); 332 input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC, 333 TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT); 334 335 usb_fill_int_urb(touchkit->irq, touchkit->udev, 336 usb_rcvintpipe(touchkit->udev, 0x81), 337 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, 338 touchkit_irq, touchkit, endpoint->bInterval); 339 340 touchkit->irq->transfer_dma = touchkit->data_dma; 341 touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 342 343 input_register_device(touchkit->input); 344 345 usb_set_intfdata(intf, touchkit); 346 return 0; 347 348out_free_buffers: 349 touchkit_free_buffers(udev, touchkit); 350out_free: 351 input_free_device(input_dev); 352 kfree(touchkit); 353 return -ENOMEM; 354} 355 356static void touchkit_disconnect(struct usb_interface *intf) 357{ 358 struct touchkit_usb *touchkit = usb_get_intfdata(intf); 359 360 dbg("%s - called", __FUNCTION__); 361 362 if (!touchkit) 363 return; 364 365 dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); 366 usb_set_intfdata(intf, NULL); 367 usb_kill_urb(touchkit->irq); 368 input_unregister_device(touchkit->input); 369 usb_free_urb(touchkit->irq); 370 touchkit_free_buffers(interface_to_usbdev(intf), touchkit); 371 kfree(touchkit); 372} 373 374MODULE_DEVICE_TABLE(usb, touchkit_devices); 375 376static struct usb_driver touchkit_driver = { 377 .name = "touchkitusb", 378 .probe = touchkit_probe, 379 .disconnect = touchkit_disconnect, 380 .id_table = touchkit_devices, 381}; 382 383static int __init touchkit_init(void) 384{ 385 return usb_register(&touchkit_driver); 386} 387 388static void __exit touchkit_cleanup(void) 389{ 390 usb_deregister(&touchkit_driver); 391} 392 393module_init(touchkit_init); 394module_exit(touchkit_cleanup); 395 396MODULE_AUTHOR(DRIVER_AUTHOR); 397MODULE_DESCRIPTION(DRIVER_DESC); 398MODULE_LICENSE("GPL");