1 /* Hey EMACS -*- linux-c -*-
3 * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
4 * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
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.
11 * Based on dabusb.c, printer.c & scanner.c
13 * Please see the file: linux/Documentation/usb/SilverLink.txt
14 * and the website at: http://lpg.ticalc.org/prj_usb/
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.
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>
37 #include <linux/ticable.h>
43 #define DRIVER_VERSION "1.07"
44 #define DRIVER_AUTHOR "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
45 #define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver"
46 #define DRIVER_LICENSE "GPL"
48 /* ----- global variables --------------------------------------------- */
50 static tiglusb_t tiglusb[MAXTIGL];
51 static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
53 /*---------- misc functions ------------------------------------------- */
56 * Re-initialize device
59 clear_device (struct usb_device *dev)
61 if (usb_reset_configuration (dev) < 0) {
62 err ("clear_device failed");
70 * Clear input & output pipes (endpoints)
73 clear_pipes (struct usb_device *dev)
77 pipe = usb_sndbulkpipe (dev, 2);
78 if (usb_clear_halt (dev, pipe)) {
79 err ("clear_pipe (w), request failed");
83 pipe = usb_rcvbulkpipe (dev, 1);
84 if (usb_clear_halt (dev, pipe)) {
85 err ("clear_pipe (r), request failed");
92 /* ----- file operations functions--------------------------------------- */
95 tiglusb_open (struct inode *inode, struct file *filp)
97 int devnum = iminor(inode);
100 if (devnum < TIUSB_MINOR || devnum >= (TIUSB_MINOR + MAXTIGL))
103 s = &tiglusb[devnum - TIUSB_MINOR];
105 if (down_interruptible (&s->mutex)) {
109 while (!s->dev || s->opened) {
112 if (filp->f_flags & O_NONBLOCK) {
116 schedule_timeout (HZ / 2);
118 if (signal_pending (current)) {
122 if (down_interruptible (&s->mutex)) {
131 filp->private_data = s;
137 tiglusb_release (struct inode *inode, struct file *filp)
139 ptiglusb_t s = (ptiglusb_t) filp->private_data;
141 if (down_interruptible (&s->mutex)) {
148 if (!s->remove_pending)
149 clear_device (s->dev);
151 wake_up (&s->remove_ok);
159 tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
161 ptiglusb_t s = (ptiglusb_t) filp->private_data;
163 int bytes_to_read = 0;
172 if (s->remove_pending)
178 buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL);
182 bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
184 pipe = usb_rcvbulkpipe (s->dev, 1);
185 result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
186 &bytes_read, (HZ * timeout) / 10);
187 if (result == -ETIMEDOUT) { /* NAK */
190 warn ("tiglusb_read, NAK received.");
193 } else if (result == -EPIPE) { /* STALL -- shouldn't happen */
194 warn ("clear_halt request to remove STALL condition.");
195 if (usb_clear_halt (s->dev, pipe))
196 err ("clear_halt, request failed");
197 clear_device (s->dev);
200 } else if (result < 0) { /* We should not get any I/O errors */
201 err ("funky result: %d. Please notify maintainer.", result);
206 if (copy_to_user (buf, buffer, bytes_read)) {
212 return ret ? ret : bytes_read;
216 tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * f_pos)
218 ptiglusb_t s = (ptiglusb_t) filp->private_data;
220 int bytes_to_write = 0;
221 int bytes_written = 0;
229 if (s->remove_pending)
235 buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL);
239 bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
240 if (copy_from_user (buffer, buf, bytes_to_write)) {
245 pipe = usb_sndbulkpipe (s->dev, 2);
246 result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
247 &bytes_written, (HZ * timeout) / 10);
249 if (result == -ETIMEDOUT) { /* NAK */
250 warn ("tiglusb_write, NAK received.");
253 } else if (result == -EPIPE) { /* STALL -- shouldn't happen */
254 warn ("clear_halt request to remove STALL condition.");
255 if (usb_clear_halt (s->dev, pipe))
256 err ("clear_halt, request failed");
257 clear_device (s->dev);
260 } else if (result < 0) { /* We should not get any I/O errors */
261 warn ("funky result: %d. Please notify maintainer.", result);
266 if (bytes_written != bytes_to_write) {
272 return ret ? ret : bytes_written;
276 tiglusb_ioctl (struct inode *inode, struct file *filp,
277 unsigned int cmd, unsigned long arg)
279 ptiglusb_t s = (ptiglusb_t) filp->private_data;
282 if (s->remove_pending)
285 if (down_interruptible (&s->mutex)) {
295 case IOCTL_TIUSB_TIMEOUT:
301 case IOCTL_TIUSB_RESET_DEVICE:
302 if (clear_device (s->dev))
305 case IOCTL_TIUSB_RESET_PIPES:
306 if (clear_pipes (s->dev))
319 /* ----- kernel module registering ------------------------------------ */
321 static struct file_operations tiglusb_fops = {
322 .owner = THIS_MODULE,
324 .read = tiglusb_read,
325 .write = tiglusb_write,
326 .ioctl = tiglusb_ioctl,
327 .open = tiglusb_open,
328 .release = tiglusb_release,
331 /* --- initialisation code ------------------------------------- */
334 tiglusb_probe (struct usb_interface *intf,
335 const struct usb_device_id *id)
337 struct usb_device *dev = interface_to_usbdev(intf);
342 dbg ("probing vendor id 0x%x, device id 0x%x",
343 dev->descriptor.idVendor, dev->descriptor.idProduct);
346 * We don't handle multiple configurations. As of version 0x0103 of
347 * the TIGL hardware, there's only 1 configuration.
350 if (dev->descriptor.bNumConfigurations != 1)
353 if ((dev->descriptor.idProduct != 0xe001)
354 && (dev->descriptor.idVendor != 0x451))
357 // NOTE: it's already in this config, this shouldn't be needed.
358 // is this working around some hardware bug?
359 if (usb_reset_configuration (dev) < 0) {
360 err ("tiglusb_probe: reset_configuration failed");
365 * Find a tiglusb struct
367 for (i = 0; i < MAXTIGL; i++) {
368 ptiglusb_t s = &tiglusb[i];
381 s->remove_pending = 0;
384 dbg ("bound to interface");
386 devfs_mk_cdev(MKDEV(TIUSB_MAJOR, TIUSB_MINOR) + s->minor,
387 S_IFCHR | S_IRUGO | S_IWUGO,
388 "ticables/usb/%d", s->minor);
390 /* Display firmware version */
391 info ("firmware revision %i.%02x",
392 dev->descriptor.bcdDevice >> 8,
393 dev->descriptor.bcdDevice & 0xff);
395 usb_set_intfdata (intf, s);
400 tiglusb_disconnect (struct usb_interface *intf)
403 ptiglusb_t s = usb_get_intfdata (intf);
405 init_waitqueue_entry(&__wait, current);
408 usb_set_intfdata (intf, NULL);
410 info ("bogus disconnect");
414 s->remove_pending = 1;
416 add_wait_queue(&s->wait, &__wait);
417 set_current_state(TASK_UNINTERRUPTIBLE);
418 if (s->state == _started)
420 current->state = TASK_RUNNING;
421 remove_wait_queue(&s->wait, &__wait);
426 devfs_remove("ticables/usb/%d", s->minor);
428 info ("device %d removed", s->minor);
433 static struct usb_device_id tiglusb_ids[] = {
434 {USB_DEVICE (0x0451, 0xe001)},
438 MODULE_DEVICE_TABLE (usb, tiglusb_ids);
440 static struct usb_driver tiglusb_driver = {
441 .owner = THIS_MODULE,
443 .probe = tiglusb_probe,
444 .disconnect = tiglusb_disconnect,
445 .id_table = tiglusb_ids,
448 /* --- initialisation code ------------------------------------- */
452 * You can use 'tiusb=timeout' to set timeout.
455 tiglusb_setup (char *str)
459 str = get_options (str, ARRAY_SIZE (ints), ints);
465 info ("tiglusb: wrong timeout value (0), using default value.");
478 /* initialize struct */
479 for (u = 0; u < MAXTIGL; u++) {
480 ptiglusb_t s = &tiglusb[u];
481 memset (s, 0, sizeof (tiglusb_t));
482 init_MUTEX (&s->mutex);
486 init_waitqueue_head (&s->wait);
487 init_waitqueue_head (&s->remove_ok);
490 /* register device */
491 if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
492 err ("unable to get major %d", TIUSB_MAJOR);
496 /* Use devfs, tree: /dev/ticables/usb/[0..3] */
497 devfs_mk_dir ("ticables/usb");
499 /* register USB module */
500 result = usb_register (&tiglusb_driver);
502 unregister_chrdev (TIUSB_MAJOR, "tiglusb");
506 info (DRIVER_DESC ", version " DRIVER_VERSION);
512 tiglusb_cleanup (void)
514 usb_deregister (&tiglusb_driver);
515 devfs_remove("ticables/usb");
516 unregister_chrdev (TIUSB_MAJOR, "tiglusb");
519 /* --------------------------------------------------------------------- */
521 __setup ("tiusb=", tiglusb_setup);
522 module_init (tiglusb_init);
523 module_exit (tiglusb_cleanup);
525 MODULE_AUTHOR (DRIVER_AUTHOR);
526 MODULE_DESCRIPTION (DRIVER_DESC);
527 MODULE_LICENSE (DRIVER_LICENSE);
529 MODULE_PARM (timeout, "i");
530 MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
532 /* --------------------------------------------------------------------- */