patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / usb / misc / tiglusb.c
1 /* Hey EMACS -*- linux-c -*-
2  *
3  * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
4  * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
5  *
6  * Copyright (C) 2001-2004:
7  *   Romain Lievin <roms@lpg.ticalc.org>
8  *   Julien BLACHE <jb@technologeek.org>
9  * under the terms of the GNU General Public License.
10  *
11  * Based on dabusb.c, printer.c & scanner.c
12  *
13  * Please see the file: linux/Documentation/usb/SilverLink.txt
14  * and the website at:  http://lpg.ticalc.org/prj_usb/
15  * for more info.
16  *
17  * History :
18  *   1.0x, Romain & Julien: initial submit.
19  *   1.03, Greg Kroah: modifications.
20  *   1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
21  *   1.05, Randy Dunlap: bug fix with the timeout parameter (divide-by-zero).
22  *   1.06, Romain: synched with 2.5, version/firmware changed (confusing).
23  *   1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
24  *          timeout argument checked in ioctl + clean-up.
25  */
26
27 #include <linux/module.h>
28 #include <linux/socket.h>
29 #include <linux/slab.h>
30 #include <linux/init.h>
31 #include <asm/uaccess.h>
32 #include <linux/delay.h>
33 #include <linux/usb.h>
34 #include <linux/smp_lock.h>
35 #include <linux/devfs_fs_kernel.h>
36 #include <linux/device.h>
37
38 #include <linux/ticable.h>
39 #include "tiglusb.h"
40
41 /*
42  * Version Information
43  */
44 #define DRIVER_VERSION "1.07"
45 #define DRIVER_AUTHOR  "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
46 #define DRIVER_DESC    "TI-GRAPH LINK USB (aka SilverLink) driver"
47 #define DRIVER_LICENSE "GPL"
48
49 /* ----- global variables --------------------------------------------- */
50
51 static tiglusb_t tiglusb[MAXTIGL];
52 static int timeout = TIMAXTIME; /* timeout in tenth of seconds     */
53 static struct class_simple *tiglusb_class;
54
55 /*---------- misc functions ------------------------------------------- */
56
57 /*
58  * Re-initialize device
59  */
60 static inline int
61 clear_device (struct usb_device *dev)
62 {
63         if (usb_reset_configuration (dev) < 0) {
64                 err ("clear_device failed");
65                 return -1;
66         }
67
68         return 0;
69 }
70
71 /* 
72  * Clear input & output pipes (endpoints)
73  */
74 static inline int
75 clear_pipes (struct usb_device *dev)
76 {
77         unsigned int pipe;
78
79         pipe = usb_sndbulkpipe (dev, 2);
80         if (usb_clear_halt (dev, pipe)) {
81                 err ("clear_pipe (w), request failed");
82                 return -1;
83         }
84
85         pipe = usb_rcvbulkpipe (dev, 1);
86         if (usb_clear_halt (dev, pipe)) {
87                 err ("clear_pipe (r), request failed");
88                 return -1;
89         }
90
91         return 0;
92 }
93
94 /* ----- file operations functions--------------------------------------- */
95
96 static int
97 tiglusb_open (struct inode *inode, struct file *filp)
98 {
99         int devnum = iminor(inode);
100         ptiglusb_t s;
101
102         if (devnum < TIUSB_MINOR || devnum >= (TIUSB_MINOR + MAXTIGL))
103                 return -EIO;
104
105         s = &tiglusb[devnum - TIUSB_MINOR];
106
107         if (down_interruptible (&s->mutex)) {
108                 return -ERESTARTSYS;
109         }
110
111         while (!s->dev || s->opened) {
112                 up (&s->mutex);
113
114                 if (filp->f_flags & O_NONBLOCK) {
115                         return -EBUSY;
116                 }
117
118                 schedule_timeout (HZ / 2);
119
120                 if (signal_pending (current)) {
121                         return -EAGAIN;
122                 }
123
124                 if (down_interruptible (&s->mutex)) {
125                         return -ERESTARTSYS;
126                 }
127         }
128
129         s->opened = 1;
130         up (&s->mutex);
131
132         filp->f_pos = 0;
133         filp->private_data = s;
134
135         return 0;
136 }
137
138 static int
139 tiglusb_release (struct inode *inode, struct file *filp)
140 {
141         ptiglusb_t s = (ptiglusb_t) filp->private_data;
142
143         if (down_interruptible (&s->mutex)) {
144                 return -ERESTARTSYS;
145         }
146
147         s->state = _stopped;
148         up (&s->mutex);
149
150         if (!s->remove_pending)
151                 clear_device (s->dev);
152         else
153                 wake_up (&s->remove_ok);
154
155         s->opened = 0;
156
157         return 0;
158 }
159
160 static ssize_t
161 tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
162 {
163         ptiglusb_t s = (ptiglusb_t) filp->private_data;
164         ssize_t ret = 0;
165         int bytes_to_read = 0;
166         int bytes_read = 0;
167         int result = 0;
168         char *buffer;
169         unsigned int pipe;
170
171         if (*f_pos)
172                 return -ESPIPE;
173
174         if (s->remove_pending)
175                 return -EIO;
176
177         if (!s->dev)
178                 return -EIO;
179
180         buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL);
181         if (!buffer)
182                 return -ENOMEM;
183
184         bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
185
186         pipe = usb_rcvbulkpipe (s->dev, 1);
187         result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
188                                &bytes_read, (HZ * timeout) / 10);
189         if (result == -ETIMEDOUT) {     /* NAK */
190                 if (!bytes_read)
191                         dbg ("quirk !");
192                 warn ("tiglusb_read, NAK received.");
193                 ret = result;
194                 goto out;
195         } else if (result == -EPIPE) {  /* STALL -- shouldn't happen */
196                 warn ("clear_halt request to remove STALL condition.");
197                 if (usb_clear_halt (s->dev, pipe))
198                         err ("clear_halt, request failed");
199                 clear_device (s->dev);
200                 ret = result;
201                 goto out;
202         } else if (result < 0) {        /* We should not get any I/O errors */
203                 err ("funky result: %d. Please notify maintainer.", result);
204                 ret = -EIO;
205                 goto out;
206         }
207
208         if (copy_to_user (buf, buffer, bytes_read)) {
209                 ret = -EFAULT;
210         }
211
212       out:
213         kfree(buffer);
214         return ret ? ret : bytes_read;
215 }
216
217 static ssize_t
218 tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * f_pos)
219 {
220         ptiglusb_t s = (ptiglusb_t) filp->private_data;
221         ssize_t ret = 0;
222         int bytes_to_write = 0;
223         int bytes_written = 0;
224         int result = 0;
225         char *buffer;
226         unsigned int pipe;
227
228         if (*f_pos)
229                 return -ESPIPE;
230
231         if (s->remove_pending)
232                 return -EIO;
233
234         if (!s->dev)
235                 return -EIO;
236
237         buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL);
238         if (!buffer)
239                 return -ENOMEM;
240
241         bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
242         if (copy_from_user (buffer, buf, bytes_to_write)) {
243                 ret = -EFAULT;
244                 goto out;
245         }
246
247         pipe = usb_sndbulkpipe (s->dev, 2);
248         result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
249                                &bytes_written, (HZ * timeout) / 10);
250
251         if (result == -ETIMEDOUT) {     /* NAK */
252                 warn ("tiglusb_write, NAK received.");
253                 ret = result;
254                 goto out;
255         } else if (result == -EPIPE) {  /* STALL -- shouldn't happen */
256                 warn ("clear_halt request to remove STALL condition.");
257                 if (usb_clear_halt (s->dev, pipe))
258                         err ("clear_halt, request failed");
259                 clear_device (s->dev);
260                 ret = result;
261                 goto out;
262         } else if (result < 0) {        /* We should not get any I/O errors */
263                 warn ("funky result: %d. Please notify maintainer.", result);
264                 ret = -EIO;
265                 goto out;
266         }
267
268         if (bytes_written != bytes_to_write) {
269                 ret = -EIO;
270         }
271
272       out:
273         kfree(buffer);
274         return ret ? ret : bytes_written;
275 }
276
277 static int
278 tiglusb_ioctl (struct inode *inode, struct file *filp,
279                unsigned int cmd, unsigned long arg)
280 {
281         ptiglusb_t s = (ptiglusb_t) filp->private_data;
282         int ret = 0;
283
284         if (s->remove_pending)
285                 return -EIO;
286
287         if (down_interruptible (&s->mutex)) {
288                 return -ERESTARTSYS;
289         }
290
291         if (!s->dev) {
292                 up (&s->mutex);
293                 return -EIO;
294         }
295
296         switch (cmd) {
297         case IOCTL_TIUSB_TIMEOUT:
298                 if (arg > 0)
299                         timeout = arg;
300                 else
301                         ret = -EINVAL;
302                 break;
303         case IOCTL_TIUSB_RESET_DEVICE:
304                 if (clear_device (s->dev))
305                         ret = -EIO;
306                 break;
307         case IOCTL_TIUSB_RESET_PIPES:
308                 if (clear_pipes (s->dev))
309                         ret = -EIO;
310                 break;
311         default:
312                 ret = -ENOTTY;
313                 break;
314         }
315
316         up (&s->mutex);
317
318         return ret;
319 }
320
321 /* ----- kernel module registering ------------------------------------ */
322
323 static struct file_operations tiglusb_fops = {
324         .owner =        THIS_MODULE,
325         .llseek =       no_llseek,
326         .read =         tiglusb_read,
327         .write =        tiglusb_write,
328         .ioctl =        tiglusb_ioctl,
329         .open =         tiglusb_open,
330         .release =      tiglusb_release,
331 };
332
333 /* --- initialisation code ------------------------------------- */
334
335 static int
336 tiglusb_probe (struct usb_interface *intf,
337                const struct usb_device_id *id)
338 {
339         struct usb_device *dev = interface_to_usbdev(intf);
340         int minor = -1;
341         int i, err = 0;
342         ptiglusb_t s;
343
344         dbg ("probing vendor id 0x%x, device id 0x%x",
345              dev->descriptor.idVendor, dev->descriptor.idProduct);
346
347         /*
348          * We don't handle multiple configurations. As of version 0x0103 of
349          * the TIGL hardware, there's only 1 configuration.
350          */
351
352         if (dev->descriptor.bNumConfigurations != 1) {
353                 err = -ENODEV;
354                 goto out;
355         }
356
357         if ((dev->descriptor.idProduct != 0xe001)
358             && (dev->descriptor.idVendor != 0x451)) {
359                 err = -ENODEV;
360                 goto out;
361         }
362
363         // NOTE:  it's already in this config, this shouldn't be needed.
364         // is this working around some hardware bug?
365         if (usb_reset_configuration (dev) < 0) {
366                 err ("tiglusb_probe: reset_configuration failed");
367                 err = -ENODEV;
368                 goto out;
369         }
370
371         /*
372          * Find a tiglusb struct
373          */
374         for (i = 0; i < MAXTIGL; i++) {
375                 ptiglusb_t s = &tiglusb[i];
376                 if (!s->dev) {
377                         minor = i;
378                         break;
379                 }
380         }
381
382         if (minor == -1) {
383                 err = -ENODEV;
384                 goto out;
385         }
386
387         s = &tiglusb[minor];
388
389         down (&s->mutex);
390         s->remove_pending = 0;
391         s->dev = dev;
392         up (&s->mutex);
393         dbg ("bound to interface");
394
395         class_simple_device_add(tiglusb_class, MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor),
396                         NULL, "usb%d", s->minor);
397         err = devfs_mk_cdev(MKDEV(TIUSB_MAJOR, TIUSB_MINOR) + s->minor,
398                         S_IFCHR | S_IRUGO | S_IWUGO,
399                         "ticables/usb/%d", s->minor);
400
401         if (err)
402                 goto out_class;
403
404         /* Display firmware version */
405         info ("firmware revision %i.%02x",
406                 dev->descriptor.bcdDevice >> 8,
407                 dev->descriptor.bcdDevice & 0xff);
408
409         usb_set_intfdata (intf, s);
410         err = 0;
411         goto out;
412
413 out_class:
414         class_simple_device_remove(MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor));
415 out:
416         return err;
417 }
418
419 static void
420 tiglusb_disconnect (struct usb_interface *intf)
421 {
422         wait_queue_t __wait;
423         ptiglusb_t s = usb_get_intfdata (intf);
424         
425         init_waitqueue_entry(&__wait, current);
426         
427
428         usb_set_intfdata (intf, NULL);
429         if (!s || !s->dev) {
430                 info ("bogus disconnect");
431                 return;
432         }
433
434         s->remove_pending = 1;
435         wake_up (&s->wait);
436         add_wait_queue(&s->wait, &__wait);
437         set_current_state(TASK_UNINTERRUPTIBLE);
438         if (s->state == _started)
439                 schedule();
440         current->state = TASK_RUNNING;
441         remove_wait_queue(&s->wait, &__wait);
442         down (&s->mutex);
443         s->dev = NULL;
444         s->opened = 0;
445
446         class_simple_device_remove(MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor));
447         devfs_remove("ticables/usb/%d", s->minor);
448
449         info ("device %d removed", s->minor);
450
451         up (&s->mutex);
452 }
453
454 static struct usb_device_id tiglusb_ids[] = {
455         {USB_DEVICE (0x0451, 0xe001)},
456         {}
457 };
458
459 MODULE_DEVICE_TABLE (usb, tiglusb_ids);
460
461 static struct usb_driver tiglusb_driver = {
462         .owner =        THIS_MODULE,
463         .name =         "tiglusb",
464         .probe =        tiglusb_probe,
465         .disconnect =   tiglusb_disconnect,
466         .id_table =     tiglusb_ids,
467 };
468
469 /* --- initialisation code ------------------------------------- */
470
471 #ifndef MODULE
472 /*
473  * You can use 'tiusb=timeout' to set timeout.
474  */
475 static int __init
476 tiglusb_setup (char *str)
477 {
478         int ints[2];
479
480         str = get_options (str, ARRAY_SIZE (ints), ints);
481
482         if (ints[0] > 0) {
483                 if (ints[1] > 0)
484                         timeout = ints[1];
485                 else
486                         info ("tiglusb: wrong timeout value (0), using default value.");
487         }
488
489         return 1;
490 }
491 #endif
492
493 static int __init
494 tiglusb_init (void)
495 {
496         unsigned u;
497         int result, err = 0;
498
499         /* initialize struct */
500         for (u = 0; u < MAXTIGL; u++) {
501                 ptiglusb_t s = &tiglusb[u];
502                 memset (s, 0, sizeof (tiglusb_t));
503                 init_MUTEX (&s->mutex);
504                 s->dev = NULL;
505                 s->minor = u;
506                 s->opened = 0;
507                 init_waitqueue_head (&s->wait);
508                 init_waitqueue_head (&s->remove_ok);
509         }
510
511         /* register device */
512         if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
513                 err ("unable to get major %d", TIUSB_MAJOR);
514                 err = -EIO;
515                 goto out;
516         }
517
518         /* Use devfs, tree: /dev/ticables/usb/[0..3] */
519         devfs_mk_dir ("ticables/usb");
520
521         tiglusb_class = class_simple_create(THIS_MODULE, "tiglusb");
522         if (IS_ERR(tiglusb_class)) {
523                 err = PTR_ERR(tiglusb_class);
524                 goto out_chrdev;
525         }
526         /* register USB module */
527         result = usb_register (&tiglusb_driver);
528         if (result < 0) {
529                 err = -1;
530                 goto out_chrdev;
531         }
532
533         info (DRIVER_DESC ", version " DRIVER_VERSION);
534
535         err = 0;
536         goto out;
537
538 out_chrdev:
539         unregister_chrdev (TIUSB_MAJOR, "tiglusb");
540 out:
541         return err;
542 }
543
544 static void __exit
545 tiglusb_cleanup (void)
546 {
547         usb_deregister (&tiglusb_driver);
548         class_simple_destroy(tiglusb_class);
549         devfs_remove("ticables/usb");
550         unregister_chrdev (TIUSB_MAJOR, "tiglusb");
551 }
552
553 /* --------------------------------------------------------------------- */
554
555 __setup ("tiusb=", tiglusb_setup);
556 module_init (tiglusb_init);
557 module_exit (tiglusb_cleanup);
558
559 MODULE_AUTHOR (DRIVER_AUTHOR);
560 MODULE_DESCRIPTION (DRIVER_DESC);
561 MODULE_LICENSE (DRIVER_LICENSE);
562
563 MODULE_PARM (timeout, "i");
564 MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
565
566 /* --------------------------------------------------------------------- */