Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc3 605 lines 16 kB view raw
1/****************************************************************************** 2 * usbtouchscreen.c 3 * Driver for USB Touchscreens, supporting those devices: 4 * - eGalax Touchkit 5 * - 3M/Microtouch 6 * - ITM 7 * - PanJit TouchSet 8 * 9 * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> 10 * Copyright (C) by Todd E. Johnson (mtouchusb.c) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of the 15 * License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 * Driver is based on touchkitusb.c 27 * - ITM parts are from itmtouch.c 28 * - 3M parts are from mtouchusb.c 29 * - PanJit parts are from an unmerged driver by Lanslott Gish 30 * 31 *****************************************************************************/ 32 33//#define DEBUG 34 35#include <linux/config.h> 36#include <linux/kernel.h> 37#include <linux/slab.h> 38#include <linux/input.h> 39#include <linux/module.h> 40#include <linux/init.h> 41#include <linux/usb.h> 42#include <linux/usb/input.h> 43 44 45#define DRIVER_VERSION "v0.3" 46#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 47#define DRIVER_DESC "USB Touchscreen Driver" 48 49static int swap_xy; 50module_param(swap_xy, bool, 0644); 51MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 52 53/* device specifc data/functions */ 54struct usbtouch_usb; 55struct usbtouch_device_info { 56 int min_xc, max_xc; 57 int min_yc, max_yc; 58 int min_press, max_press; 59 int rept_size; 60 int flags; 61 62 void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len); 63 int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press); 64 int (*init) (struct usbtouch_usb *usbtouch); 65}; 66 67#define USBTOUCH_FLG_BUFFER 0x01 68 69 70/* a usbtouch device */ 71struct usbtouch_usb { 72 unsigned char *data; 73 dma_addr_t data_dma; 74 unsigned char *buffer; 75 int buf_len; 76 struct urb *irq; 77 struct usb_device *udev; 78 struct input_dev *input; 79 struct usbtouch_device_info *type; 80 char name[128]; 81 char phys[64]; 82}; 83 84static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 85 struct pt_regs *regs, unsigned char *pkt, int len); 86 87/* device types */ 88enum { 89 DEVTPYE_DUMMY = -1, 90 DEVTYPE_EGALAX, 91 DEVTYPE_PANJIT, 92 DEVTYPE_3M, 93 DEVTYPE_ITM, 94}; 95 96static struct usb_device_id usbtouch_devices[] = { 97#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX 98 {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 99 {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 100 {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 101 {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 102#endif 103 104#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT 105 {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 106 {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 107 {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 108 {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 109#endif 110 111#ifdef CONFIG_USB_TOUCHSCREEN_3M 112 {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 113#endif 114 115#ifdef CONFIG_USB_TOUCHSCREEN_ITM 116 {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 117#endif 118 119 {} 120}; 121 122 123/***************************************************************************** 124 * eGalax part 125 */ 126 127#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX 128 129#define EGALAX_PKT_TYPE_MASK 0xFE 130#define EGALAX_PKT_TYPE_REPT 0x80 131#define EGALAX_PKT_TYPE_DIAG 0x0A 132 133static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) 134{ 135 if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 136 return 0; 137 138 *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 139 *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 140 *touch = pkt[0] & 0x01; 141 142 return 1; 143 144} 145 146static int egalax_get_pkt_len(unsigned char *buf) 147{ 148 switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 149 case EGALAX_PKT_TYPE_REPT: 150 return 5; 151 152 case EGALAX_PKT_TYPE_DIAG: 153 return buf[1] + 2; 154 } 155 156 return 0; 157} 158 159static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs, 160 unsigned char *pkt, int len) 161{ 162 unsigned char *buffer; 163 int pkt_len, buf_len, pos; 164 165 /* if the buffer contains data, append */ 166 if (unlikely(usbtouch->buf_len)) { 167 int tmp; 168 169 /* if only 1 byte in buffer, add another one to get length */ 170 if (usbtouch->buf_len == 1) 171 usbtouch->buffer[1] = pkt[0]; 172 173 pkt_len = egalax_get_pkt_len(usbtouch->buffer); 174 175 /* unknown packet: drop everything */ 176 if (!pkt_len) 177 return; 178 179 /* append, process */ 180 tmp = pkt_len - usbtouch->buf_len; 181 memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 182 usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len); 183 184 buffer = pkt + tmp; 185 buf_len = len - tmp; 186 } else { 187 buffer = pkt; 188 buf_len = len; 189 } 190 191 /* only one byte left in buffer */ 192 if (unlikely(buf_len == 1)) { 193 usbtouch->buffer[0] = buffer[0]; 194 usbtouch->buf_len = 1; 195 return; 196 } 197 198 /* loop over the buffer */ 199 pos = 0; 200 while (pos < buf_len) { 201 /* get packet len */ 202 pkt_len = egalax_get_pkt_len(buffer + pos); 203 204 /* unknown packet: drop everything */ 205 if (unlikely(!pkt_len)) 206 return; 207 208 /* full packet: process */ 209 if (likely(pkt_len <= buf_len)) { 210 usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len); 211 } else { 212 /* incomplete packet: save in buffer */ 213 memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 214 usbtouch->buf_len = buf_len - pos; 215 } 216 pos += pkt_len; 217 } 218} 219#endif 220 221 222/***************************************************************************** 223 * PanJit Part 224 */ 225#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT 226static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) 227{ 228 *x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 229 *y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 230 *touch = pkt[0] & 0x01; 231 232 return 1; 233} 234#endif 235 236 237/***************************************************************************** 238 * 3M/Microtouch Part 239 */ 240#ifdef CONFIG_USB_TOUCHSCREEN_3M 241 242#define MTOUCHUSB_ASYNC_REPORT 1 243#define MTOUCHUSB_RESET 7 244#define MTOUCHUSB_REQ_CTRLLR_ID 10 245 246static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) 247{ 248 *x = (pkt[8] << 8) | pkt[7]; 249 *y = (pkt[10] << 8) | pkt[9]; 250 *touch = (pkt[2] & 0x40) ? 1 : 0; 251 252 return 1; 253} 254 255static int mtouch_init(struct usbtouch_usb *usbtouch) 256{ 257 int ret; 258 259 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 260 MTOUCHUSB_RESET, 261 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 262 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 263 dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", 264 __FUNCTION__, ret); 265 if (ret < 0) 266 return ret; 267 268 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 269 MTOUCHUSB_ASYNC_REPORT, 270 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 271 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 272 dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", 273 __FUNCTION__, ret); 274 if (ret < 0) 275 return ret; 276 277 return 0; 278} 279#endif 280 281 282/***************************************************************************** 283 * ITM Part 284 */ 285#ifdef CONFIG_USB_TOUCHSCREEN_ITM 286static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) 287{ 288 *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 289 *x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 290 *press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F); 291 *touch = ~pkt[7] & 0x20; 292 293 return 1; 294} 295#endif 296 297 298/***************************************************************************** 299 * the different device descriptors 300 */ 301static struct usbtouch_device_info usbtouch_dev_info[] = { 302#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX 303 [DEVTYPE_EGALAX] = { 304 .min_xc = 0x0, 305 .max_xc = 0x07ff, 306 .min_yc = 0x0, 307 .max_yc = 0x07ff, 308 .rept_size = 16, 309 .flags = USBTOUCH_FLG_BUFFER, 310 .process_pkt = egalax_process, 311 .read_data = egalax_read_data, 312 }, 313#endif 314 315#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT 316 [DEVTYPE_PANJIT] = { 317 .min_xc = 0x0, 318 .max_xc = 0x0fff, 319 .min_yc = 0x0, 320 .max_yc = 0x0fff, 321 .rept_size = 8, 322 .read_data = panjit_read_data, 323 }, 324#endif 325 326#ifdef CONFIG_USB_TOUCHSCREEN_3M 327 [DEVTYPE_3M] = { 328 .min_xc = 0x0, 329 .max_xc = 0x4000, 330 .min_yc = 0x0, 331 .max_yc = 0x4000, 332 .rept_size = 11, 333 .read_data = mtouch_read_data, 334 .init = mtouch_init, 335 }, 336#endif 337 338#ifdef CONFIG_USB_TOUCHSCREEN_ITM 339 [DEVTYPE_ITM] = { 340 .min_xc = 0x0, 341 .max_xc = 0x0fff, 342 .min_yc = 0x0, 343 .max_yc = 0x0fff, 344 .max_press = 0xff, 345 .rept_size = 8, 346 .read_data = itm_read_data, 347 }, 348#endif 349}; 350 351 352/***************************************************************************** 353 * Generic Part 354 */ 355static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 356 struct pt_regs *regs, unsigned char *pkt, int len) 357{ 358 int x, y, touch, press; 359 struct usbtouch_device_info *type = usbtouch->type; 360 361 if (!type->read_data(pkt, &x, &y, &touch, &press)) 362 return; 363 364 input_regs(usbtouch->input, regs); 365 input_report_key(usbtouch->input, BTN_TOUCH, touch); 366 367 if (swap_xy) { 368 input_report_abs(usbtouch->input, ABS_X, y); 369 input_report_abs(usbtouch->input, ABS_Y, x); 370 } else { 371 input_report_abs(usbtouch->input, ABS_X, x); 372 input_report_abs(usbtouch->input, ABS_Y, y); 373 } 374 if (type->max_press) 375 input_report_abs(usbtouch->input, ABS_PRESSURE, press); 376 input_sync(usbtouch->input); 377} 378 379 380static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) 381{ 382 struct usbtouch_usb *usbtouch = urb->context; 383 int retval; 384 385 switch (urb->status) { 386 case 0: 387 /* success */ 388 break; 389 case -ETIMEDOUT: 390 /* this urb is timing out */ 391 dbg("%s - urb timed out - was the device unplugged?", 392 __FUNCTION__); 393 return; 394 case -ECONNRESET: 395 case -ENOENT: 396 case -ESHUTDOWN: 397 /* this urb is terminated, clean up */ 398 dbg("%s - urb shutting down with status: %d", 399 __FUNCTION__, urb->status); 400 return; 401 default: 402 dbg("%s - nonzero urb status received: %d", 403 __FUNCTION__, urb->status); 404 goto exit; 405 } 406 407 usbtouch->type->process_pkt(usbtouch, regs, usbtouch->data, urb->actual_length); 408 409exit: 410 retval = usb_submit_urb(urb, GFP_ATOMIC); 411 if (retval) 412 err("%s - usb_submit_urb failed with result: %d", 413 __FUNCTION__, retval); 414} 415 416static int usbtouch_open(struct input_dev *input) 417{ 418 struct usbtouch_usb *usbtouch = input->private; 419 420 usbtouch->irq->dev = usbtouch->udev; 421 422 if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) 423 return -EIO; 424 425 return 0; 426} 427 428static void usbtouch_close(struct input_dev *input) 429{ 430 struct usbtouch_usb *usbtouch = input->private; 431 432 usb_kill_urb(usbtouch->irq); 433} 434 435 436static void usbtouch_free_buffers(struct usb_device *udev, 437 struct usbtouch_usb *usbtouch) 438{ 439 if (usbtouch->data) 440 usb_buffer_free(udev, usbtouch->type->rept_size, 441 usbtouch->data, usbtouch->data_dma); 442 kfree(usbtouch->buffer); 443} 444 445 446static int usbtouch_probe(struct usb_interface *intf, 447 const struct usb_device_id *id) 448{ 449 struct usbtouch_usb *usbtouch; 450 struct input_dev *input_dev; 451 struct usb_host_interface *interface; 452 struct usb_endpoint_descriptor *endpoint; 453 struct usb_device *udev = interface_to_usbdev(intf); 454 struct usbtouch_device_info *type; 455 int err; 456 457 interface = intf->cur_altsetting; 458 endpoint = &interface->endpoint[0].desc; 459 460 usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 461 input_dev = input_allocate_device(); 462 if (!usbtouch || !input_dev) 463 goto out_free; 464 465 type = &usbtouch_dev_info[id->driver_info]; 466 usbtouch->type = type; 467 if (!type->process_pkt) 468 type->process_pkt = usbtouch_process_pkt; 469 470 usbtouch->data = usb_buffer_alloc(udev, type->rept_size, 471 SLAB_KERNEL, &usbtouch->data_dma); 472 if (!usbtouch->data) 473 goto out_free; 474 475 if (type->flags & USBTOUCH_FLG_BUFFER) { 476 usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 477 if (!usbtouch->buffer) 478 goto out_free_buffers; 479 } 480 481 usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 482 if (!usbtouch->irq) { 483 dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); 484 goto out_free_buffers; 485 } 486 487 usbtouch->udev = udev; 488 usbtouch->input = input_dev; 489 490 if (udev->manufacturer) 491 strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 492 493 if (udev->product) { 494 if (udev->manufacturer) 495 strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 496 strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 497 } 498 499 if (!strlen(usbtouch->name)) 500 snprintf(usbtouch->name, sizeof(usbtouch->name), 501 "USB Touchscreen %04x:%04x", 502 le16_to_cpu(udev->descriptor.idVendor), 503 le16_to_cpu(udev->descriptor.idProduct)); 504 505 usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 506 strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 507 508 input_dev->name = usbtouch->name; 509 input_dev->phys = usbtouch->phys; 510 usb_to_input_id(udev, &input_dev->id); 511 input_dev->cdev.dev = &intf->dev; 512 input_dev->private = usbtouch; 513 input_dev->open = usbtouch_open; 514 input_dev->close = usbtouch_close; 515 516 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 517 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 518 input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 519 input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 520 if (type->max_press) 521 input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 522 type->max_press, 0, 0); 523 524 usb_fill_int_urb(usbtouch->irq, usbtouch->udev, 525 usb_rcvintpipe(usbtouch->udev, 0x81), 526 usbtouch->data, type->rept_size, 527 usbtouch_irq, usbtouch, endpoint->bInterval); 528 529 usbtouch->irq->transfer_dma = usbtouch->data_dma; 530 usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 531 532 /* device specific init */ 533 if (type->init) { 534 err = type->init(usbtouch); 535 if (err) { 536 dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); 537 goto out_free_buffers; 538 } 539 } 540 541 err = input_register_device(usbtouch->input); 542 if (err) { 543 dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); 544 goto out_free_buffers; 545 } 546 547 usb_set_intfdata(intf, usbtouch); 548 549 return 0; 550 551out_free_buffers: 552 usbtouch_free_buffers(udev, usbtouch); 553out_free: 554 input_free_device(input_dev); 555 kfree(usbtouch); 556 return -ENOMEM; 557} 558 559static void usbtouch_disconnect(struct usb_interface *intf) 560{ 561 struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 562 563 dbg("%s - called", __FUNCTION__); 564 565 if (!usbtouch) 566 return; 567 568 dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); 569 usb_set_intfdata(intf, NULL); 570 usb_kill_urb(usbtouch->irq); 571 input_unregister_device(usbtouch->input); 572 usb_free_urb(usbtouch->irq); 573 usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 574 kfree(usbtouch); 575} 576 577MODULE_DEVICE_TABLE(usb, usbtouch_devices); 578 579static struct usb_driver usbtouch_driver = { 580 .name = "usbtouchscreen", 581 .probe = usbtouch_probe, 582 .disconnect = usbtouch_disconnect, 583 .id_table = usbtouch_devices, 584}; 585 586static int __init usbtouch_init(void) 587{ 588 return usb_register(&usbtouch_driver); 589} 590 591static void __exit usbtouch_cleanup(void) 592{ 593 usb_deregister(&usbtouch_driver); 594} 595 596module_init(usbtouch_init); 597module_exit(usbtouch_cleanup); 598 599MODULE_AUTHOR(DRIVER_AUTHOR); 600MODULE_DESCRIPTION(DRIVER_DESC); 601MODULE_LICENSE("GPL"); 602 603MODULE_ALIAS("touchkitusb"); 604MODULE_ALIAS("itmtouch"); 605MODULE_ALIAS("mtouchusb");