Messages in this thread Patches in this message | | | Date | Sun, 31 Mar 2002 22:31:23 +0200 | From | Romain Liévin <> | Subject | Re: Subject: kernel 2.5.7, tiusb: SilverLink cable driver for TI graphing calculators |
| |
Hi,
> > this is a new driver for handling a TI-GRAPH LINK USB (aka SilverLink) > > cable > > designed to connect a Texas Instruments graphing calculators to a > > computer/workstation through USB. > > > > This driver has an official device number. > > Do you want to add this driver to the drivers/usb/ directory with the > rest of the kernel USB drivers? If so, please send me a patch.
Yes, I would like to add it. You will find the complete patch below. BTW, I recently requested device numbers to John Cagle for 3 TI related modules. The USB module shares its major with the others.
> 115 char TI link cable devices (115 was formerly the console driver speaker) > 0 = /dev/tipar0 Parallel cable on first parallel port > ... > 7 = /dev/tipar7 Parallel cable on seventh parallel port > > 8 = /dev/tiser0 Serial cable on first serial port > ... > 15 = /dev/tiser7 Serial cable on seventh serial port > > 16 = /dev/tiusb0 First USB cable > ... > 47 = /dev/tiusb31 32nd USB cable
I do not know whether it's the best thing to do. The 2 others use the same bit-banging scheme and could be grouped under a sub-system (such as I2C). The USB module is different. Maybe it's better to register it under the USB sub-system...
Thanks, Romain.
==============================[ cut here ]============================== --- linux.orig/drivers/usb/tiglusb.c Sun Mar 31 22:02:56 2002 +++ linux/drivers/usb/tiglusb.c Sun Mar 31 22:05:05 2002 @@ -0,0 +1,524 @@ +/* Hey EMACS -*- linux-c -*- + * + * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver. + * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org). + * + * Copyright (C) 2001-2002: + * Romain Lievin <roms@lpg.ticalc.org> + * Julien BLACHE <jb@technologeek.org> + * under the terms of the GNU General Public License. + * + * Based on dabusb.c, printer.c & scanner.c + * + * Please see the file: linux/Documentation/usb/SilverLink.txt + * and the website at: http://lpg.ticalc.org/prj_usb/ + * for more info. + * + */ + +#include <linux/module.h> +#include <linux/socket.h> +#include <linux/miscdevice.h> +#include <linux/list.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <asm/uaccess.h> +#include <asm/atomic.h> +#include <linux/delay.h> +#include <linux/usb.h> +#include <linux/smp_lock.h> +#include <linux/devfs_fs_kernel.h> + +#include <linux/ticable.h> +#include "tiglusb.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "1.02" +#define DRIVER_AUTHOR "Romain Lievin <roms@lpg.ticalc.org> & Julien Blache <jb@jblache.org>" +#define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver" +#define DRIVER_LICENSE "GPL" + +#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) +#if LINUX_VERSION_CODE < VERSION(2,5,0) +# define minor(x) MINOR(x) +#endif + +/* ----- global variables --------------------------------------------- */ + +static tiglusb_t tiglusb[MAXTIGL]; +static int timeout = TIMAXTIME; /* timeout in tenth of seconds */ + +static devfs_handle_t devfs_handle; + +/*---------- misc functions -----------------------------------------------*/ + +/* Unregister device */ +static void usblp_cleanup (tiglusb_t *s) +{ + devfs_unregister (s->devfs); + //memset(tiglusb[s->minor], 0, sizeof(tiglusb_t)); + info ("tiglusb%d removed", s->minor); +} + +/* Re-initialize device */ +static int clear_device(struct usb_device *dev) +{ + if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) + { + printk("tiglusb: clear_device failed\n"); + return -1; + } + + return 0; +} + +/* Clear input & output pipes (endpoints) */ +static int clear_pipes(struct usb_device *dev) +{ + unsigned int pipe; + + pipe = usb_sndbulkpipe (dev, 1); + if(usb_clear_halt(dev, usb_pipeendpoint(pipe))) { + printk("tiglusb: clear_pipe (r), request failed\n"); + return -1; + } + + pipe = usb_sndbulkpipe (dev, 2); + if(usb_clear_halt(dev, usb_pipeendpoint(pipe))) { + printk("tiglusb: clear_pipe (w), request failed\n"); + return -1; + } + + return 0; +} + +/* ----- kernel module functions--------------------------------------- */ + +// ok +static int tiglusb_open(struct inode *inode, struct file *file) +{ + int devnum = minor(inode->i_rdev); + ptiglusb_t s; + + if (devnum < TIUSB_MINOR || devnum >= (TIUSB_MINOR + MAXTIGL)) + return -EIO; + + s = &tiglusb[devnum - TIUSB_MINOR]; + + down(&s->mutex); + + while (!s->dev || s->opened) { + up (&s->mutex); + + if (file->f_flags & O_NONBLOCK) { + return -EBUSY; + } + schedule_timeout (HZ / 2); + + if (signal_pending (current)) { + return -EAGAIN; + } + down (&s->mutex); + } + + s->opened = 1; + up(&s->mutex); + + file->f_pos = 0; + file->private_data = s; + + return 0; +} + +//ok +static int tiglusb_release(struct inode *inode, struct file *file) +{ + ptiglusb_t s = (ptiglusb_t) file->private_data; + + lock_kernel(); + down (&s->mutex); + s->state = _stopped; + up (&s->mutex); + + if (!s->remove_pending) + clear_device(s->dev); + else + wake_up (&s->remove_ok); + + s->opened = 0; + unlock_kernel(); + + return 0; +} + +// +static ssize_t tiglusb_read(struct file *file, char *buf, + size_t count, loff_t * ppos) +{ + ptiglusb_t s = (ptiglusb_t) file->private_data; + ssize_t ret = 0; + int bytes_to_read = 0; + int bytes_read = 0; + int result = 0; + char buffer[BULK_RCV_MAX]; + unsigned int pipe; + + if (*ppos) + return -ESPIPE; + + if (s->remove_pending) + return -EIO; + + if (!s->dev) + return -EIO; + + bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count; + + pipe = usb_rcvbulkpipe (s->dev, 1); + result = usb_bulk_msg(s->dev, pipe, buffer, bytes_to_read, + &bytes_read, HZ/(timeout/10)); + if (result == -ETIMEDOUT) { /* NAK */ + ret = result; + if(!bytes_read) { + printk("quirk !\n"); + } + warn("tiglusb_read, NAK received."); + goto out; + } + else if (result == -EPIPE) { /* STALL -- shouldn't happen */ + warn("CLEAR_FEATURE request to remove STALL condition.\n"); + if(usb_clear_halt(s->dev, usb_pipeendpoint(pipe))) + warn("send_packet, request failed\n"); + //clear_device(s->dev); + ret = result; + goto out; + } + else if (result < 0) { /* We should not get any I/O errors */ + warn("funky result: %d. Please notify maintainer.", result); + ret = -EIO; + goto out; + } + + if (copy_to_user(buf, buffer, bytes_read)) { + ret = -EFAULT; + goto out; + } + + out: + return ret ? ret : bytes_read; +} + +// +static ssize_t tiglusb_write(struct file *file, const char *buf, + size_t count, loff_t * ppos) +{ + ptiglusb_t s = (ptiglusb_t) file->private_data; + ssize_t ret = 0; + int bytes_to_write = 0; + int bytes_written = 0; + int result = 0; + char buffer[BULK_SND_MAX]; + unsigned int pipe; + + if (*ppos) + return -ESPIPE; + + if (s->remove_pending) + return -EIO; + + if (!s->dev) + return -EIO; + + bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count; + if (copy_from_user(buffer, buf, bytes_to_write)) { + ret = -EFAULT; + goto out; + } + + pipe = usb_sndbulkpipe (s->dev, 2); + result = usb_bulk_msg(s->dev, pipe, buffer, bytes_to_write, + &bytes_written, HZ/(timeout/10)); + + if (result == -ETIMEDOUT) { /* NAK */ + warn("tiglusb_write, NAK received."); + ret = result; + goto out; + } + else if (result == -EPIPE) { /* STALL -- shouldn't happen */ + warn("CLEAR_FEATURE request to remove STALL condition.\n"); + if(usb_clear_halt(s->dev, usb_pipeendpoint(pipe))) + warn("send_packet, request failed\n"); + //clear_device(s->dev); + ret = result; + goto out; + } + else if (result < 0) { /* We should not get any I/O errors */ + warn("funky result: %d. Please notify maintainer.", result); + ret = -EIO; + goto out; + } + + if (bytes_written != bytes_to_write) { + ret = -EIO; + goto out; + } + + out: + return ret ? ret : bytes_written; +} + +//ok +static int tiglusb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + ptiglusb_t s = (ptiglusb_t) file->private_data; + int ret = 0; + + if (s->remove_pending) + return -EIO; + + down (&s->mutex); + + if (!s->dev) { + up (&s->mutex); + return -EIO; + } + + switch (cmd) + { + case IOCTL_TIUSB_TIMEOUT: + timeout = arg ; // timeout value is passed in tenth of seconds + break; + case IOCTL_TIUSB_RESET_DEVICE: + printk(KERN_DEBUG "IOCTL_TIGLUSB_RESET_DEVICE\n"); + if(clear_device(s->dev)) + ret = -EIO; + break; + case IOCTL_TIUSB_RESET_PIPES: + printk(KERN_DEBUG "IOCTL_TIGLUSB_RESET_PIPES\n"); + if(clear_pipes(s->dev)) + ret = -EIO; + break; + default: + ret = -ENOTTY; + break; + } + + up (&s->mutex); + + return ret; +} + +/* ----- kernel module registering ------------------------------------ */ + +static struct file_operations tiglusb_fops = +{ + owner: THIS_MODULE, + llseek: no_llseek, + read: tiglusb_read, + write: tiglusb_write, + ioctl: tiglusb_ioctl, + open: tiglusb_open, + release: tiglusb_release, +}; + +//ok +static int tiglusb_find_struct (void) +{ + int u; + + for (u=0; u<MAXTIGL; u++) + { + ptiglusb_t s = &tiglusb[u]; + if (!s->dev) + return u; + } + + return -1; +} + +/* --- initialisation code ------------------------------------- */ + +//ok +static void *tiglusb_probe (struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + int minor; + ptiglusb_t s; + char name[8]; + + printk("tiglusb: probing vendor id 0x%x, device id 0x%x ifnum:%d\n", + dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); + + /* + * We don't handle multiple configurations. As of version 0x0103 of + * the TIGL hardware, there's only 1 configuration. + */ + + if (dev->descriptor.bNumConfigurations != 1) + return NULL; + + if ((dev->descriptor.idProduct != 0xe001) && + (dev->descriptor.idVendor != 0x451)) + return NULL; + + if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) { + printk("tiglusb_probe: set_configuration failed\n"); + return NULL; + } + + minor = tiglusb_find_struct (); + if (minor == -1) + return NULL; + + s = &tiglusb[minor]; + + down (&s->mutex); + s->remove_pending = 0; + s->dev = dev; + up (&s->mutex); + dbg("bound to interface: %d", ifnum); + + sprintf(name, "%d", s->minor); + printk("tiglusb: registering to devfs : major = %d, minor = %d, node = %s\n", TIUSB_MAJOR, (TIUSB_MINOR + s->minor), name); + s->devfs = devfs_register(devfs_handle, name, + DEVFS_FL_DEFAULT, TIUSB_MAJOR, + TIUSB_MINOR + s->minor, + S_IFCHR | S_IRUGO | S_IWUGO, + &tiglusb_fops, NULL); + + /* Display firmware version */ + printk("tiglusb: link cable version %i.%02x\n", + dev->descriptor.bcdDevice >> 8, + dev->descriptor.bcdDevice & 0xff); + + return s; +} + +//ok +static void tiglusb_disconnect (struct usb_device *dev, void *drv_context) +{ + ptiglusb_t s = (ptiglusb_t) drv_context; + + if (!s || !s->dev) + printk("bogus disconnect"); + + s->remove_pending = 1; + wake_up (&s->wait); + if (s->state == _started) + sleep_on (&s->remove_ok); + s->dev = NULL; + s->opened = 0; + + /* cleanup now or later, on close*/ + if (!s->opened) + usblp_cleanup (s); + else + up (&s->mutex); + + /* unregister device */ + devfs_unregister(s->devfs); s->devfs = NULL; + printk("tiglusb: device disconnected\n"); +} + +static struct usb_device_id tiglusb_ids [] = { + { USB_DEVICE(0x0451, 0xe001) }, + { } +}; + +MODULE_DEVICE_TABLE (usb, tiglusb_ids); + +static struct usb_driver tiglusb_driver = +{ + name: "tiglusb", + probe: tiglusb_probe, + disconnect: tiglusb_disconnect, + fops: &tiglusb_fops, + minor: TIUSB_MINOR, + id_table: tiglusb_ids, +}; + +/* --- initialisation code ------------------------------------- */ + +#ifndef MODULE +/* You must set these - there is no sane way to probe for this cable. + * You can use 'tipar=timeout,delay' to set these now. */ +static int __init tiglusb_setup (char *str) +{ + int ints[2]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) { + timeout = ints[1]; + } + + return 1; +} +#endif + +static int __init tiglusb_init (void) +{ + unsigned u; + int result; + + /* initialize struct */ + for (u = 0; u < MAXTIGL; u++) + { + ptiglusb_t s = &tiglusb[u]; + memset (s, 0, sizeof (tiglusb_t)); + init_MUTEX (&s->mutex); + s->dev = NULL; + s->minor = u; + s->opened = 0; + init_waitqueue_head (&s->wait); + init_waitqueue_head (&s->remove_ok); + } + + /* register device */ + if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { + printk("tiglusb: unable to get major %d\n", TIUSB_MAJOR); + return -EIO; + } + + /* Use devfs, tree: /dev/ticables/usb/[0..3]*/ + devfs_handle = devfs_mk_dir(NULL, "ticables/usb", NULL); + + /* register USB module */ + result = usb_register(&tiglusb_driver); + if (result < 0) { + devfs_unregister_chrdev(TIUSB_MAJOR, "tiglusb"); + return -1; + } + + info(DRIVER_DESC ", " DRIVER_VERSION); + + return 0; +} + +static void __exit tiglusb_cleanup (void) +{ + usb_deregister (&tiglusb_driver); + devfs_unregister (devfs_handle); + devfs_unregister_chrdev(TIUSB_MAJOR, "tiglusb"); +} + +/* --------------------------------------------------------------------- */ + +__setup("tipar=", tiglusb_setup); +module_init(tiglusb_init); +module_exit(tiglusb_cleanup); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE(DRIVER_LICENSE); + +EXPORT_NO_SYMBOLS; + +MODULE_PARM(timeout, "i"); +MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)"); + +/* --------------------------------------------------------------------- */ --- linux.orig/drivers/usb/tiglusb.h Sun Mar 31 22:02:57 2002 +++ linux/drivers/usb/tiglusb.h Sun Mar 31 22:05:05 2002 @@ -0,0 +1,58 @@ +/* Hey EMACS -*- linux-c -*- + * + * tiglusb - low level driver for SilverLink cable + * + * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org> + * under the terms of the GNU General Public License. + * + * Redistribution of this file is permitted under the terms of the GNU + * Public License (GPL) + */ + +#ifndef _TIGLUSB_H +#define _TIGLUSB_H + +/* + * Max. number of devices supported + */ +#define MAXTIGL 16 + +/* + * Max. packetsize for IN and OUT pipes + */ +#define BULK_RCV_MAX 32 +#define BULK_SND_MAX 32 + +/* + * The driver context... + */ + +typedef enum { _stopped=0, _started } driver_state_t; + +typedef struct +{ + struct usb_device *dev; /* USB device handle */ + struct semaphore mutex; /* locks this struct */ + struct semaphore sem; + + wait_queue_head_t wait; /* for timed waits */ + wait_queue_head_t remove_ok; + + int minor; /* which minor dev #? */ + devfs_handle_t devfs; /* devfs device */ + + driver_state_t state; /* started/stopped */ + int opened; /* tru if open */ + int remove_pending; + + struct urb readurb, writeurb; /* The urbs */ + int wcomplete, rcomplete; /* R/W is complete */ + + char rd_buf[BULK_RCV_MAX]; /* read buffer */ + char wr_buf[BULK_SND_MAX]; /* write buffer */ + +} tiglusb_t, *ptiglusb_t; + +extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ + +#endif --- linux.orig/include/linux/ticable.h Sun Mar 31 22:05:42 2002 +++ linux/include/linux/ticable.h Sun Mar 31 22:05:53 2002 @@ -0,0 +1,42 @@ +/* Hey EMACS -*- linux-c -*- + * + * tipar/tiser/tiusb - low level driver for handling link cables + * designed for Texas Instruments graphing calculators. + * + * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org> + * + * Redistribution of this file is permitted under the terms of the GNU + * Public License (GPL) + */ + +#ifndef _TICABLE_H +#define _TICABLE_H 1 + +/* Internal default constants for the kernel module */ +#define TIMAXTIME 15 /* 1.5 seconds */ +#define IO_DELAY 10 /* 10 micro-seconds */ + +/* Major & minor number for character devices */ +#define TIPAR_MAJOR 115 /* 0 to 7 */ +#define TIPAR_MINOR 0 + +#define TISER_MAJOR 115 /* 8 to 15 */ +#define TISER_MINOR 8 + +#define TIUSB_MAJOR 115 /* 16 to 31 */ +#define TIUSB_MINOR 16 + +/* + * Request values for the 'ioctl' function. + */ +#define IOCTL_TIPAR_DELAY _IOW('p', 0xa8, int) /* set delay */ +#define IOCTL_TIPAR_TIMEOUT _IOW('p', 0xa9, int) /* set timeout */ + +#define IOCTL_TISER_DELAY _IOW('p', 0xa0, int) /* set delay */ +#define IOCTL_TISER_TIMEOUT _IOW('p', 0xa1, int) /* set timeout */ + +#define IOCTL_TIUSB_TIMEOUT _IOW('N', 0x20, int) /* set timeout */ +#define IOCTL_TIUSB_RESET_DEVICE _IOW('N', 0x21, int) /* reset device */ +#define IOCTL_TIUSB_RESET_PIPES _IOW('N', 0x22, int) /* reset both pipes*/ + +#endif /* TICABLE_H */ --- linux.orig/MAINTAINERS Mon Mar 18 21:37:04 2002 +++ linux/MAINTAINERS Sun Mar 31 22:01:20 2002 @@ -1502,6 +1502,13 @@ M: hch@infradead.org S: Maintained +TI GRAPH LINK USB (SilverLink) CABLE DRIVER +P: Romain Lievin +M: roms@lpg.ticalc.org +P: Julien Blache +M: jb@technologeek.org +S: Maintained + TLAN NETWORK DRIVER P: Torben Mathiasen M: torben.mathiasen@compaq.com --- linux.orig/drivers/usb/Config.help Mon Mar 18 21:37:13 2002 +++ linux/drivers/usb/Config.help Sun Mar 31 22:09:36 2002 @@ -626,3 +626,21 @@ The module will be called bluetooth.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +CONFIG_USB_TIGL + If you own a Texas Instruments graphing calculator and use a + TI-GRAPH LINK USB cable (aka SilverLink), then you might be + interested in this driver. + + If you enable this driver, you will be able to communicate with + your calculator through a set of device nodes under /dev. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called tiglusb.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + If you don't know what the SilverLink cable is or what a Texas + Instruments graphing calculator is, then you probably don't need this + driver. + + If unsure, say N. \ No newline at end of file --- linux.orig/drivers/usb/Config.in Mon Mar 18 21:37:13 2002 +++ linux/drivers/usb/Config.in Sun Mar 31 22:00:49 2002 @@ -101,6 +101,7 @@ comment 'USB Miscellaneous drivers' dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL + dep_tristate 'Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB fi endmenu --- linux.orig/drivers/usb/Makefile Mon Mar 18 21:37:18 2002 +++ linux/drivers/usb/Makefile Sun Mar 31 22:01:46 2002 @@ -86,6 +86,7 @@ obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o obj-$(CONFIG_USB_USBNET) += usbnet.o obj-$(CONFIG_USB_AUERSWALD) += auerswald.o +obj-$(CONFIG_USB_TIGL) += tiglusb.o # Object files in subdirectories mod-subdirs := serial hcd --- linux.orig/Documentation/usb/silverlink.txt Sun Mar 31 22:02:45 2002 +++ linux/Documentation/usb/silverlink.txt Sun Mar 31 22:07:08 2002 @@ -0,0 +1,80 @@ +------------------------------------------------------------------------- +Readme for Linux device driver for the Texas Instruments SilverLink cable +------------------------------------------------------------------------- + +Author: Romain Liévin & Julien Blache +Homepage: http://lpg.ticalc.org/prj_usb + +INTRODUCTION: + +This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable +designed by TI for connecting their TI8x/9x calculators to a computer +(PC or Mac usually). + +If you need more information, please visit the 'SilverLink drivers' homepage +at the above URL. + +WHAT YOU NEED: + +A TI calculator of course and a program capable to communicate with your +calculator. +TiLP will work for sure (since I am his developer !). yal92 may be able to use +it by changing tidev for tiglusb (may require some hacking...). + +HOW TO USE IT: + +You must have first compiled USB support, support for your specific USB host +controller (UHCI or OHCI). + +Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX): + + insmod usb/usbcore.o + insmod usb/usb-uhci.o <OR> insmod usb/ohci-hcd.o + insmod tiglusb.o + +If it is not already there (it usually is), create the device: + + mknod /dev/tiglusb0 c 115 16 + +You will have to set permissions on this device to allow you to read/write +from it: + + chmod 666 /dev/tiglusb0 + +Now you are ready to run a linking program such as TiLP. Be sure to configure +it properly (RTFM). + +MODULE PARAMETERS: + + You can set these with: insmod tiglusb NAME=VALUE + There is currently no way to set these on a per-cable basis. + + NAME: timeout + TYPE: integer + DEFAULT: 15 + DESC: Timeout value in tenth of seconds. If no data is available once this + time has expired then the driver will return with a timeout error. + +QUIRKS: + +The following problem seems to be specific to the link cable since it appears +on all platforms (Linux, Windows, Mac OS-X). + +In some very particular cases, the driver returns with success but +without any data. The application should retry a read operation at least once. + +HOW TO CONTACT US: + +You can email me at roms@lpg.ticalc.org. Please prefix the subject line +with "TIGLUSB: " so that I am certain to notice your message. +You can also mail JB at jb@jblache.org: he has written the first release of +this driver but he better knows the Mac OS-X driver. + +CREDITS: + +The code is based on dabusb.c, printer.c and scanner.c ! +The driver has been developed independantly of Texas Instruments. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |