Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 272 lines 7.8 kB view raw
1/****************************************************************************** 2 * itmtouch.c -- Driver for ITM touchscreen panel 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 * 18 * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. 19 * 20 * Kudos to ITM for providing me with the datasheet for the panel, 21 * even though it was a day later than I had finished writing this 22 * driver. 23 * 24 * It has meant that I've been able to correct my interpretation of the 25 * protocol packets however. 26 * 27 * CC -- 2003/9/29 28 * 29 * History 30 * 1.0 & 1.1 2003 (CC) vojtech@suse.cz 31 * Original version for 2.4.x kernels 32 * 33 * 1.2 02/03/2005 (HCE) hc@mivu.no 34 * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. 35 * Unfortunately no calibration support at this time. 36 * 37 * 1.2.1 09/03/2005 (HCE) hc@mivu.no 38 * Code cleanup and adjusting syntax to start matching kernel standards 39 * 40 *****************************************************************************/ 41 42#include <linux/config.h> 43#include <linux/kernel.h> 44#include <linux/slab.h> 45#include <linux/input.h> 46#include <linux/module.h> 47#include <linux/init.h> 48#include <linux/usb.h> 49#include <linux/usb_input.h> 50 51/* only an 8 byte buffer necessary for a single packet */ 52#define ITM_BUFSIZE 8 53#define PATH_SIZE 64 54 55#define USB_VENDOR_ID_ITMINC 0x0403 56#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 57 58#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" 59#define DRIVER_VERSION "v1.2.1" 60#define DRIVER_DESC "USB ITM Inc Touch Panel Driver" 61#define DRIVER_LICENSE "GPL" 62 63MODULE_AUTHOR( DRIVER_AUTHOR ); 64MODULE_DESCRIPTION( DRIVER_DESC ); 65MODULE_LICENSE( DRIVER_LICENSE ); 66 67struct itmtouch_dev { 68 struct usb_device *usbdev; /* usb device */ 69 struct input_dev *inputdev; /* input device */ 70 struct urb *readurb; /* urb */ 71 char rbuf[ITM_BUFSIZE]; /* data */ 72 int users; 73 char name[128]; 74 char phys[64]; 75}; 76 77static struct usb_device_id itmtouch_ids [] = { 78 { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, 79 { } 80}; 81 82static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) 83{ 84 struct itmtouch_dev *itmtouch = urb->context; 85 unsigned char *data = urb->transfer_buffer; 86 struct input_dev *dev = itmtouch->inputdev; 87 int retval; 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 input_regs(dev, regs); 112 113 /* if pressure has been released, then don't report X/Y */ 114 if (data[7] & 0x20) { 115 input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); 116 input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); 117 } 118 119 input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); 120 input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); 121 input_sync(dev); 122 123exit: 124 retval = usb_submit_urb (urb, GFP_ATOMIC); 125 if (retval) 126 printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", 127 __FUNCTION__, retval); 128} 129 130static int itmtouch_open(struct input_dev *input) 131{ 132 struct itmtouch_dev *itmtouch = input->private; 133 134 itmtouch->readurb->dev = itmtouch->usbdev; 135 136 if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) 137 return -EIO; 138 139 return 0; 140} 141 142static void itmtouch_close(struct input_dev *input) 143{ 144 struct itmtouch_dev *itmtouch = input->private; 145 146 usb_kill_urb(itmtouch->readurb); 147} 148 149static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) 150{ 151 struct itmtouch_dev *itmtouch; 152 struct input_dev *input_dev; 153 struct usb_host_interface *interface; 154 struct usb_endpoint_descriptor *endpoint; 155 struct usb_device *udev = interface_to_usbdev(intf); 156 unsigned int pipe; 157 unsigned int maxp; 158 159 interface = intf->cur_altsetting; 160 endpoint = &interface->endpoint[0].desc; 161 162 itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL); 163 input_dev = input_allocate_device(); 164 if (!itmtouch || !input_dev) { 165 err("%s - Out of memory.", __FUNCTION__); 166 goto fail; 167 } 168 169 itmtouch->usbdev = udev; 170 itmtouch->inputdev = input_dev; 171 172 if (udev->manufacturer) 173 strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name)); 174 175 if (udev->product) { 176 if (udev->manufacturer) 177 strlcat(itmtouch->name, " ", sizeof(itmtouch->name)); 178 strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name)); 179 } 180 181 if (!strlen(itmtouch->name)) 182 sprintf(itmtouch->name, "USB ITM touchscreen"); 183 184 usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys)); 185 strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys)); 186 187 input_dev->name = itmtouch->name; 188 input_dev->phys = itmtouch->phys; 189 usb_to_input_id(udev, &input_dev->id); 190 input_dev->cdev.dev = &intf->dev; 191 input_dev->private = itmtouch; 192 193 input_dev->open = itmtouch_open; 194 input_dev->close = itmtouch_close; 195 196 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 197 input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); 198 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 199 200 /* device limits */ 201 /* as specified by the ITM datasheet, X and Y are 12bit, 202 * Z (pressure) is 8 bit. However, the fields are defined up 203 * to 14 bits for future possible expansion. 204 */ 205 input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0); 206 input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0); 207 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0); 208 209 /* initialise the URB so we can read from the transport stream */ 210 pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); 211 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 212 213 if (maxp > ITM_BUFSIZE) 214 maxp = ITM_BUFSIZE; 215 216 itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); 217 if (!itmtouch->readurb) { 218 dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); 219 goto fail; 220 } 221 222 usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, 223 maxp, itmtouch_irq, itmtouch, endpoint->bInterval); 224 225 input_register_device(itmtouch->inputdev); 226 227 usb_set_intfdata(intf, itmtouch); 228 229 return 0; 230 231 fail: input_free_device(input_dev); 232 kfree(itmtouch); 233 return -ENOMEM; 234} 235 236static void itmtouch_disconnect(struct usb_interface *intf) 237{ 238 struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); 239 240 usb_set_intfdata(intf, NULL); 241 242 if (itmtouch) { 243 input_unregister_device(itmtouch->inputdev); 244 usb_kill_urb(itmtouch->readurb); 245 usb_free_urb(itmtouch->readurb); 246 kfree(itmtouch); 247 } 248} 249 250MODULE_DEVICE_TABLE(usb, itmtouch_ids); 251 252static struct usb_driver itmtouch_driver = { 253 .name = "itmtouch", 254 .probe = itmtouch_probe, 255 .disconnect = itmtouch_disconnect, 256 .id_table = itmtouch_ids, 257}; 258 259static int __init itmtouch_init(void) 260{ 261 info(DRIVER_DESC " " DRIVER_VERSION); 262 info(DRIVER_AUTHOR); 263 return usb_register(&itmtouch_driver); 264} 265 266static void __exit itmtouch_exit(void) 267{ 268 usb_deregister(&itmtouch_driver); 269} 270 271module_init(itmtouch_init); 272module_exit(itmtouch_exit);