Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.18 269 lines 7.7 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/kernel.h> 43#include <linux/slab.h> 44#include <linux/module.h> 45#include <linux/init.h> 46#include <linux/usb/input.h> 47 48/* only an 8 byte buffer necessary for a single packet */ 49#define ITM_BUFSIZE 8 50#define PATH_SIZE 64 51 52#define USB_VENDOR_ID_ITMINC 0x0403 53#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 54 55#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" 56#define DRIVER_VERSION "v1.2.1" 57#define DRIVER_DESC "USB ITM Inc Touch Panel Driver" 58#define DRIVER_LICENSE "GPL" 59 60MODULE_AUTHOR( DRIVER_AUTHOR ); 61MODULE_DESCRIPTION( DRIVER_DESC ); 62MODULE_LICENSE( DRIVER_LICENSE ); 63 64struct itmtouch_dev { 65 struct usb_device *usbdev; /* usb device */ 66 struct input_dev *inputdev; /* input device */ 67 struct urb *readurb; /* urb */ 68 char rbuf[ITM_BUFSIZE]; /* data */ 69 int users; 70 char name[128]; 71 char phys[64]; 72}; 73 74static struct usb_device_id itmtouch_ids [] = { 75 { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, 76 { } 77}; 78 79static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) 80{ 81 struct itmtouch_dev *itmtouch = urb->context; 82 unsigned char *data = urb->transfer_buffer; 83 struct input_dev *dev = itmtouch->inputdev; 84 int retval; 85 86 switch (urb->status) { 87 case 0: 88 /* success */ 89 break; 90 case -ETIMEDOUT: 91 /* this urb is timing out */ 92 dbg("%s - urb timed out - was the device unplugged?", 93 __FUNCTION__); 94 return; 95 case -ECONNRESET: 96 case -ENOENT: 97 case -ESHUTDOWN: 98 /* this urb is terminated, clean up */ 99 dbg("%s - urb shutting down with status: %d", 100 __FUNCTION__, urb->status); 101 return; 102 default: 103 dbg("%s - nonzero urb status received: %d", 104 __FUNCTION__, urb->status); 105 goto exit; 106 } 107 108 input_regs(dev, regs); 109 110 /* if pressure has been released, then don't report X/Y */ 111 if (data[7] & 0x20) { 112 input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); 113 input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); 114 } 115 116 input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); 117 input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); 118 input_sync(dev); 119 120exit: 121 retval = usb_submit_urb (urb, GFP_ATOMIC); 122 if (retval) 123 printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", 124 __FUNCTION__, retval); 125} 126 127static int itmtouch_open(struct input_dev *input) 128{ 129 struct itmtouch_dev *itmtouch = input->private; 130 131 itmtouch->readurb->dev = itmtouch->usbdev; 132 133 if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) 134 return -EIO; 135 136 return 0; 137} 138 139static void itmtouch_close(struct input_dev *input) 140{ 141 struct itmtouch_dev *itmtouch = input->private; 142 143 usb_kill_urb(itmtouch->readurb); 144} 145 146static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) 147{ 148 struct itmtouch_dev *itmtouch; 149 struct input_dev *input_dev; 150 struct usb_host_interface *interface; 151 struct usb_endpoint_descriptor *endpoint; 152 struct usb_device *udev = interface_to_usbdev(intf); 153 unsigned int pipe; 154 unsigned int maxp; 155 156 interface = intf->cur_altsetting; 157 endpoint = &interface->endpoint[0].desc; 158 159 itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL); 160 input_dev = input_allocate_device(); 161 if (!itmtouch || !input_dev) { 162 err("%s - Out of memory.", __FUNCTION__); 163 goto fail; 164 } 165 166 itmtouch->usbdev = udev; 167 itmtouch->inputdev = input_dev; 168 169 if (udev->manufacturer) 170 strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name)); 171 172 if (udev->product) { 173 if (udev->manufacturer) 174 strlcat(itmtouch->name, " ", sizeof(itmtouch->name)); 175 strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name)); 176 } 177 178 if (!strlen(itmtouch->name)) 179 sprintf(itmtouch->name, "USB ITM touchscreen"); 180 181 usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys)); 182 strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys)); 183 184 input_dev->name = itmtouch->name; 185 input_dev->phys = itmtouch->phys; 186 usb_to_input_id(udev, &input_dev->id); 187 input_dev->cdev.dev = &intf->dev; 188 input_dev->private = itmtouch; 189 190 input_dev->open = itmtouch_open; 191 input_dev->close = itmtouch_close; 192 193 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 194 input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); 195 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 196 197 /* device limits */ 198 /* as specified by the ITM datasheet, X and Y are 12bit, 199 * Z (pressure) is 8 bit. However, the fields are defined up 200 * to 14 bits for future possible expansion. 201 */ 202 input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0); 203 input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0); 204 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0); 205 206 /* initialise the URB so we can read from the transport stream */ 207 pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); 208 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 209 210 if (maxp > ITM_BUFSIZE) 211 maxp = ITM_BUFSIZE; 212 213 itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); 214 if (!itmtouch->readurb) { 215 dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); 216 goto fail; 217 } 218 219 usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, 220 maxp, itmtouch_irq, itmtouch, endpoint->bInterval); 221 222 input_register_device(itmtouch->inputdev); 223 224 usb_set_intfdata(intf, itmtouch); 225 226 return 0; 227 228 fail: input_free_device(input_dev); 229 kfree(itmtouch); 230 return -ENOMEM; 231} 232 233static void itmtouch_disconnect(struct usb_interface *intf) 234{ 235 struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); 236 237 usb_set_intfdata(intf, NULL); 238 239 if (itmtouch) { 240 input_unregister_device(itmtouch->inputdev); 241 usb_kill_urb(itmtouch->readurb); 242 usb_free_urb(itmtouch->readurb); 243 kfree(itmtouch); 244 } 245} 246 247MODULE_DEVICE_TABLE(usb, itmtouch_ids); 248 249static struct usb_driver itmtouch_driver = { 250 .name = "itmtouch", 251 .probe = itmtouch_probe, 252 .disconnect = itmtouch_disconnect, 253 .id_table = itmtouch_ids, 254}; 255 256static int __init itmtouch_init(void) 257{ 258 info(DRIVER_DESC " " DRIVER_VERSION); 259 info(DRIVER_AUTHOR); 260 return usb_register(&itmtouch_driver); 261} 262 263static void __exit itmtouch_exit(void) 264{ 265 usb_deregister(&itmtouch_driver); 266} 267 268module_init(itmtouch_init); 269module_exit(itmtouch_exit);