ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / usb / input / mtouchusb.c
1 /******************************************************************************
2  * mtouchusb.c  --  Driver for Microtouch (Now 3M) USB Touchscreens
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 Radoslaw Garbacz (usb-support@ite.pl)
19  *  (http://freshmeat.net/projects/3mtouchscreendriver)
20  *
21  * History
22  *
23  *  0.3 & 0.4  2002 (TEJ) tejohnson@yahoo.com
24  *    Updated to 2.4.18, then 2.4.19
25  *    Old version still relied on stealing a minor
26  *
27  *  0.5  02/26/2004 (TEJ) tejohnson@yahoo.com
28  *    Complete rewrite using Linux Input in 2.6.3
29  *    Unfortunately no calibration support at this time
30  *
31  *****************************************************************************/
32
33 #include <linux/config.h>
34
35 #ifdef CONFIG_USB_DEBUG
36         #define DEBUG
37 #else
38         #undef DEBUG
39 #endif
40
41 #include <linux/kernel.h>
42 #include <linux/slab.h>
43 #include <linux/input.h>
44 #include <linux/module.h>
45 #include <linux/init.h>
46 #include <linux/usb.h>
47
48 #define MTOUCHUSB_MIN_XC                0xc8
49 #define MTOUCHUSB_MAX_XC                0xff78
50 #define MTOUCHUSB_XC_FUZZ               0x0
51 #define MTOUCHUSB_XC_FLAT               0x0
52 #define MTOUCHUSB_MIN_YC                0x0
53 #define MTOUCHUSB_MAX_YC                0xff78
54 #define MTOUCHUSB_YC_FUZZ               0x0
55 #define MTOUCHUSB_YC_FLAT               0x0
56 #define MTOUCHUSB_ASYC_REPORT           1
57 #define MTOUCHUSB_REPORT_SIZE_DATA      11
58 #define MTOUCHUSB_REQ_CTRLLR_ID         10
59
60 #define MTOUCHUSB_GET_XC(data)          (data[4]<<8 | data[3])
61 #define MTOUCHUSB_GET_YC(data)          (data[6]<<8 | data[5])
62 #define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
63
64 #define DRIVER_VERSION "v0.1"
65 #define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
66 #define DRIVER_DESC "Microtouch USB HID Touchscreen Driver"
67
68 struct mtouch_usb {
69         unsigned char *data;
70         dma_addr_t data_dma;
71         struct urb *irq;
72         struct usb_device *udev;
73         struct input_dev input;
74         int open;
75         char name[128];
76         char phys[64];
77 };
78
79 static __s32 vendor=-1, product=-1;
80
81 static struct usb_device_id mtouchusb_devices [] = {
82         { USB_DEVICE(0x0596, 0x0001) }, /* 3M (Formerly MicroTouch) 14-206 */
83         { }                             /* Terminating entry */
84 };
85
86 static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
87 {
88         struct mtouch_usb *mtouch = urb->context;
89         int retval;
90
91         switch (urb->status) {
92                 case 0:
93                         /* success */
94                         break;
95                 case -ETIMEDOUT:
96                         /* this urb is timing out */
97                         dbg("%s - urb timed out - was the device unplugged?",
98                             __FUNCTION__);
99                         return;
100                 case -ECONNRESET:
101                 case -ENOENT:
102                 case -ESHUTDOWN:
103                         /* this urb is terminated, clean up */
104                         dbg("%s - urb shutting down with status: %d",
105                             __FUNCTION__, urb->status);
106                         return;
107                 default:
108                         dbg("%s - nonzero urb status received: %d",
109                             __FUNCTION__, urb->status);
110                         goto exit;
111         }
112
113         input_regs(&mtouch->input, regs);
114         input_report_key(&mtouch->input, BTN_TOUCH,
115                          MTOUCHUSB_GET_TOUCHED(mtouch->data));
116         input_report_abs(&mtouch->input, ABS_X,
117                          MTOUCHUSB_GET_XC(mtouch->data));
118         input_report_abs(&mtouch->input, ABS_Y,
119                          MTOUCHUSB_GET_YC(mtouch->data));
120         input_sync(&mtouch->input);
121
122 exit:
123         retval = usb_submit_urb (urb, GFP_ATOMIC);
124         if (retval)
125                 err ("%s - usb_submit_urb failed with result: %d",
126                      __FUNCTION__, retval);
127 }
128
129 static int mtouchusb_open (struct input_dev *input)
130 {
131         struct mtouch_usb *mtouch = input->private;
132
133         if (mtouch->open++)
134                 return 0;
135
136         mtouch->irq->dev = mtouch->udev;
137
138         if (usb_submit_urb (mtouch->irq, GFP_ATOMIC))
139                 return -EIO;
140
141         return 0;
142 }
143
144 static void mtouchusb_close (struct input_dev *input)
145 {
146         struct mtouch_usb *mtouch = input->private;
147
148         if (!--mtouch->open)
149                 usb_unlink_urb (mtouch->irq);
150 }
151
152 static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
153 {
154         dbg("%s - called", __FUNCTION__);
155
156         mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_SIZE_DATA,
157                                         SLAB_ATOMIC, &mtouch->data_dma);
158
159         if (!mtouch->data)
160                 return -1;
161
162         return 0;
163 }
164
165 static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
166 {
167         dbg("%s - called", __FUNCTION__);
168
169         if (mtouch->data)
170                 usb_buffer_free(udev, MTOUCHUSB_REPORT_SIZE_DATA,
171                                 mtouch->data, mtouch->data_dma);
172 }
173
174 static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
175 {
176         struct mtouch_usb *mtouch;
177         struct usb_host_interface *interface;
178         struct usb_endpoint_descriptor *endpoint;
179         struct usb_device *udev = interface_to_usbdev (intf);
180         char path[64];
181         char *buf;
182         int nRet;
183         int ix;
184         char valid_device = 0;
185
186         dbg("%s - called", __FUNCTION__);
187         if (vendor != -1 && product != -1) {
188                 info("%s - User specified USB Touch -- Vend:Prod - %x:%x",
189                      __FUNCTION__, vendor, product);
190         }
191
192         for (ix = 0; ix < sizeof (mtouchusb_devices) /
193              sizeof (struct usb_device_id); ix++) {
194                 if ((udev->descriptor.idVendor ==
195                      mtouchusb_devices [ix].idVendor) &&
196                      (udev->descriptor.idProduct ==
197                      mtouchusb_devices [ix].idProduct)) {
198                         valid_device = 1;
199                         break;
200                 }
201         }
202
203         if (udev->descriptor.idVendor == vendor &&
204             udev->descriptor.idProduct == product) {  /* User specified */
205                 valid_device = 1;
206         }
207
208         if (!valid_device) {
209                 err("%s - No valid device!", __FUNCTION__);
210                 return -EIO;
211         }
212
213         if (udev->descriptor.bNumConfigurations != 1) {
214                 err("%s -  Only one device configuration is supported.",
215                     __FUNCTION__);
216                 return -EIO;
217         }
218
219         dbg("%s - setting interface", __FUNCTION__);
220         interface = intf->cur_altsetting;
221
222         dbg("%s - setting endpoint", __FUNCTION__);
223         endpoint = &interface->endpoint[0].desc;
224
225         if (interface->desc.bNumEndpoints != 1) {
226                 err("%s - Only one endpoint is supported.", __FUNCTION__);
227                 return -EIO;
228         }
229
230         if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) {
231                 err("%s - Out of memory.", __FUNCTION__);
232                 return -ENOMEM;
233         }
234
235         memset(mtouch, 0, sizeof(struct mtouch_usb));
236         mtouch->udev = udev;
237
238         dbg("%s - allocating buffers", __FUNCTION__);
239         if (mtouchusb_alloc_buffers(udev, mtouch)) {
240                 mtouchusb_free_buffers(udev, mtouch);
241                 kfree(mtouch);
242                 return -ENOMEM;
243         }
244
245         mtouch->input.private = mtouch;
246         mtouch->input.open = mtouchusb_open;
247         mtouch->input.close = mtouchusb_close;
248
249         usb_make_path(udev, path, 64);
250         sprintf(mtouch->phys, "%s/input0", path);
251
252         mtouch->input.name = mtouch->name;
253         mtouch->input.phys = mtouch->phys;
254         mtouch->input.id.bustype = BUS_USB;
255         mtouch->input.id.vendor = udev->descriptor.idVendor;
256         mtouch->input.id.product = udev->descriptor.idProduct;
257         mtouch->input.id.version = udev->descriptor.bcdDevice;
258         mtouch->input.dev = &intf->dev;
259
260         mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
261         mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
262         mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
263
264         /* Used to Scale Compensated Data and Flip Y */
265         mtouch->input.absmin[ABS_X] =  MTOUCHUSB_MIN_XC;
266         mtouch->input.absmax[ABS_X] =  MTOUCHUSB_MAX_XC;
267         mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
268         mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
269         mtouch->input.absmin[ABS_Y] =  MTOUCHUSB_MAX_YC;
270         mtouch->input.absmax[ABS_Y] =  MTOUCHUSB_MIN_YC;
271         mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
272         mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
273
274         if (!(buf = kmalloc(63, GFP_KERNEL))) {
275                 kfree(mtouch);
276                 return -ENOMEM;
277         }
278
279         if (udev->descriptor.iManufacturer &&
280             usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
281                         strcat(mtouch->name, buf);
282         if (udev->descriptor.iProduct &&
283             usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
284                         sprintf(mtouch->name, "%s %s", mtouch->name, buf);
285
286         if (!strlen(mtouch->name))
287                 sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
288                         mtouch->input.id.vendor, mtouch->input.id.product);
289
290         kfree(buf);
291
292         nRet = usb_control_msg(mtouch->udev,
293                                usb_rcvctrlpipe(udev, 0x80),
294                                USB_REQ_GET_CONFIGURATION,
295                                USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
296                                0,
297                                0x81,
298                                NULL,
299                                0,
300                                HZ * USB_CTRL_SET_TIMEOUT);
301         dbg("%s - usb_control_msg - USB_REQ_GET_CONFIGURATION - bytes|err: %d",
302             __FUNCTION__, nRet);
303
304         dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__);
305         mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
306         if (!mtouch->irq) {
307                 dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
308                 mtouchusb_free_buffers(udev, mtouch);
309                 kfree(mtouch);
310                 return -ENOMEM;
311         }
312
313         dbg("%s - usb_fill_int_urb", __FUNCTION__);
314         usb_fill_int_urb(mtouch->irq,
315                          mtouch->udev,
316                          usb_rcvintpipe(mtouch->udev, 0x81),
317                          mtouch->data,
318                          MTOUCHUSB_REPORT_SIZE_DATA,
319                          mtouchusb_irq,
320                          mtouch,
321                          endpoint->bInterval);
322
323         dbg("%s - input_register_device", __FUNCTION__);
324         input_register_device(&mtouch->input);
325
326         nRet = usb_control_msg(mtouch->udev,
327                                usb_rcvctrlpipe(udev, 0x80),
328                                MTOUCHUSB_ASYC_REPORT,
329                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
330                                MTOUCHUSB_ASYC_REPORT,
331                                MTOUCHUSB_ASYC_REPORT,
332                                NULL,
333                                0,
334                                HZ * USB_CTRL_SET_TIMEOUT);
335         dbg("%s - usb_control_msg - MTOUCHUSB_ASYC_REPORT - bytes|err: %d",
336             __FUNCTION__, nRet);
337
338         printk(KERN_INFO "input: %s on %s\n", mtouch->name, path);
339         usb_set_intfdata(intf, mtouch);
340
341         return 0;
342 }
343
344 static void mtouchusb_disconnect(struct usb_interface *intf)
345 {
346         struct mtouch_usb *mtouch = usb_get_intfdata (intf);
347
348         dbg("%s - called", __FUNCTION__);
349         usb_set_intfdata(intf, NULL);
350         if (mtouch) {
351                 dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
352                 usb_unlink_urb(mtouch->irq);
353                 input_unregister_device(&mtouch->input);
354                 usb_free_urb(mtouch->irq);
355                 mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
356                 kfree(mtouch);
357         }
358 }
359
360 MODULE_DEVICE_TABLE (usb, mtouchusb_devices);
361
362 static struct usb_driver mtouchusb_driver = {
363         .owner =      THIS_MODULE,
364         .name =       "mtouchusb",
365         .probe =      mtouchusb_probe,
366         .disconnect = mtouchusb_disconnect,
367         .id_table =   mtouchusb_devices,
368 };
369
370 static int __init mtouchusb_init(void) {
371         dbg("%s - called", __FUNCTION__);
372         return usb_register(&mtouchusb_driver);
373 }
374
375 static void __exit mtouchusb_cleanup(void) {
376         dbg("%s - called", __FUNCTION__);
377         usb_deregister(&mtouchusb_driver);
378 }
379
380 module_init(mtouchusb_init);
381 module_exit(mtouchusb_cleanup);
382
383 MODULE_AUTHOR( DRIVER_AUTHOR );
384 MODULE_DESCRIPTION( DRIVER_DESC );
385 MODULE_LICENSE("GPL");
386 MODULE_PARM(vendor, "i");
387 MODULE_PARM_DESC(vendor, "User specified USB idVendor");
388 MODULE_PARM(product, "i");
389 MODULE_PARM_DESC(product, "User specified USB idProduct");
390
391