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