ChangeSet 1.1608.84.10, 2004/03/09 14:12:08-08:00, [EMAIL PROTECTED]

[PATCH] USB brlvger: Driver obsoleted by rewrite using usbfs

We have rewritten the brlvger (Tieman Voyager USB Braille display) driver
so that it works from user-space through usbfs. It appears to work just as
well as the in-kernel driver.

The brlvger driver in the 2.6.x kernel is now obsolete and should be
removed. The attached patch against 2.6.3 does this. Please apply.
NB: The following files are completely deleted:
    Documentation/usb/brlvger.txt
    drivers/usb/misc/brlvger.c
    include/linux/brlvger.h

The new Voyager driver is available (stil under GPL) as part of BRLTTY,
starting with version 3.5pre1 (http://mielke.cc/brltty).
Thanks to Dave Mielke who implemented BRLTTY's usbfs functionality, among
lots of other stuff.


 Documentation/usb/brlvger.txt |   36 -
 drivers/usb/misc/brlvger.c    | 1016 ------------------------------------------
 include/linux/brlvger.h       |   54 --
 CREDITS                       |   10 
 MAINTAINERS                   |    7 
 drivers/usb/Makefile          |    1 
 drivers/usb/misc/Kconfig      |   11 
 drivers/usb/misc/Makefile     |    1 
 8 files changed, 1136 deletions(-)


diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS   Tue Mar 16 15:03:20 2004
+++ b/CREDITS   Tue Mar 16 15:03:20 2004
@@ -673,11 +673,6 @@
 S: NN1 3QT
 S: United Kingdom
 
-N: Stephane Dalton
-E: [EMAIL PROTECTED]
-D: Tieman Voyager USB Braille display driver.
-S: Québec, Canada
-
 N: Uwe Dannowski
 E: [EMAIL PROTECTED]
 W: http://i30www.ira.uka.de/~dannowsk/
@@ -796,11 +791,6 @@
 E: [EMAIL PROTECTED]
 W: http://www.fsmlabs.com/linuxppcbk.html
 D: PowerPC
-
-N: Stéphane Doyon
-E: [EMAIL PROTECTED]
-D: Tieman Voyager USB Braille display driver.
-S: Québec, Canada
 
 N: Oleg Drokin
 E: [EMAIL PROTECTED]
diff -Nru a/Documentation/usb/brlvger.txt b/Documentation/usb/brlvger.txt
--- a/Documentation/usb/brlvger.txt     Tue Mar 16 15:03:20 2004
+++ /dev/null   Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-Kernel Driver for the Tieman Voyager Braille Display (USB)
-
-Authors:
-Stéphane Dalton <[EMAIL PROTECTED]>
-Stéphane Doyon  <[EMAIL PROTECTED]>
-
-Version 0.8, April 17, 2002
-
-The brlvger driver supports a Braille display (aka Braille terminal)
-model Voyager from Tieman.
-
-The driver has been in heavy use for about six months now (as of April
-17th 2002) by a very few users (about 3-4), who say it has worked very
-well for them.
-
-We have tested it with a Voyager 44, but it should also support
-the Voyager 70.
-
-This driver implements a character device which allows userspace programs
-access to the braille displays raw functions. You still need a userspace
-program to perform the screen-review functions and control the
-display. Get BRLTTY from http://mielke.cc/brltty/ (version 2.99.8 or
-later). It has a Voyager driver which interfaces with this kernel driver.
-
-The interface is through a character device, major 180, minor 128, called
-"brlvger" under devfs.
-
-Many thanks to the Tieman people: Corand van Strien, Ivar Illing, Daphne
-Vogelaar and Ingrid Vogel. They provided us with a Braille display (as
-well as programming information) so that we could write this driver. They
-replaced the display when it broke and they answered our technical
-questions. It is very motivating when companies take an interest in such
-projects and are so supportive.
-
-Thanks to Andor Demarteau <[EMAIL PROTECTED]> who got this whole
-project started and beta-tested all our early buggy attempts.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS       Tue Mar 16 15:03:20 2004
+++ b/MAINTAINERS       Tue Mar 16 15:03:20 2004
@@ -1966,13 +1966,6 @@
 M:     [EMAIL PROTECTED]
 S:     Maintained
 
-TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
-P:     Stephane Dalton
-M:     [EMAIL PROTECTED]
-P:     Stéphane Doyon
-M:     [EMAIL PROTECTED]
-S:     Maintained
-
 TLAN NETWORK DRIVER
 P:     Samuel Chessman
 M:     [EMAIL PROTECTED]
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile      Tue Mar 16 15:03:20 2004
+++ b/drivers/usb/Makefile      Tue Mar 16 15:03:20 2004
@@ -55,7 +55,6 @@
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
 obj-$(CONFIG_USB_AUERSWALD)    += misc/
-obj-$(CONFIG_USB_BRLVGER)      += misc/
 obj-$(CONFIG_USB_EMI26)                += misc/
 obj-$(CONFIG_USB_LCD)          += misc/
 obj-$(CONFIG_USB_LEGOTOWER)    += misc/
diff -Nru a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
--- a/drivers/usb/misc/Kconfig  Tue Mar 16 15:03:20 2004
+++ b/drivers/usb/misc/Kconfig  Tue Mar 16 15:03:20 2004
@@ -86,17 +86,6 @@
          a module, say M here and read
          <file:Documentation/kbuild/modules.txt>.
 
-config USB_BRLVGER
-       tristate "Tieman Voyager USB Braille display support (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
-       help
-         Say Y here if you want to use the Voyager USB Braille display from
-         Tieman. See <file:Documentation/usb/brlvger.txt> for more
-         information.
-
-         To compile this driver as a module, choose M here: the
-         module will be called brlvger.
-
 config USB_LCD
        tristate "USB LCD driver support"
        depends on USB
diff -Nru a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
--- a/drivers/usb/misc/Makefile Tue Mar 16 15:03:20 2004
+++ b/drivers/usb/misc/Makefile Tue Mar 16 15:03:20 2004
@@ -4,7 +4,6 @@
 #
 
 obj-$(CONFIG_USB_AUERSWALD)    += auerswald.o
-obj-$(CONFIG_USB_BRLVGER)      += brlvger.o
 obj-$(CONFIG_USB_EMI62)                += emi62.o
 obj-$(CONFIG_USB_EMI26)                += emi26.o
 obj-$(CONFIG_USB_LCD)          += usblcd.o
diff -Nru a/drivers/usb/misc/brlvger.c b/drivers/usb/misc/brlvger.c
--- a/drivers/usb/misc/brlvger.c        Tue Mar 16 15:03:20 2004
+++ /dev/null   Wed Dec 31 16:00:00 1969
@@ -1,1016 +0,0 @@
-/*
- *      Tieman Voyager braille display USB driver.
- *
- *      Copyright 2001-2002 Stephane Dalton <[EMAIL PROTECTED]>
- *                      and Stéphane Doyon  <[EMAIL PROTECTED]>
- *            Maintained by Stéphane Doyon  <[EMAIL PROTECTED]>.
- */
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/* History:
- * 0.8 April 2002: Integration into the kernel tree.
- * 0.7 October 2001: First public release as a module, distributed with
- *     the BRLTTY package (beta versions around 2.99y).
- */
-
-#define DRIVER_VERSION "v0.8"
-#define DATE "April 2002"
-#define DRIVER_AUTHOR \
-       "Stephane Dalton <[EMAIL PROTECTED]> " \
-       "and Stéphane Doyon <[EMAIL PROTECTED]>"
-#define DRIVER_DESC "Tieman Voyager braille display USB driver for Linux 2.4"
-#define DRIVER_SHORTDESC "Voyager"
-
-#define BANNER \
-       KERN_INFO DRIVER_SHORTDESC " " DRIVER_VERSION " (" DATE ")\n" \
-       KERN_INFO "   by " DRIVER_AUTHOR "\n"
-
-static const char longbanner[] = {
-       DRIVER_DESC ", " DRIVER_VERSION " (" DATE "), by " DRIVER_AUTHOR
-};
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/poll.h>
-#include <linux/brlvger.h>
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-/* Module parameters */
-
-static int debug = 1;
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level, 0-3");
-
-static int write_repeats = 2;
-MODULE_PARM(write_repeats, "i");
-MODULE_PARM_DESC(write_repeats, "Hack: repetitions for command to "
-                "display braille pattern");
-                /* to get rid of weird extra dots (perhaps only on
-                   early hardware versions?) */
-
-static int stall_tries = 3;
-MODULE_PARM(stall_tries, "i");
-MODULE_PARM_DESC(stall_tries, "Hack: retransmits of stalled USB "
-                "control messages");
-                 /* broken early hardware versions? */
-
-#define BRLVGER_RAW_VOLTAGE 89
-/* from 0->300V to 255->200V, we are told 265V is normal operating voltage,
-   but we don't know the scale. Assuming it is linear. */
-static int raw_voltage = BRLVGER_RAW_VOLTAGE;
-MODULE_PARM(raw_voltage, "i");
-MODULE_PARM_DESC(raw_voltage, "Parameter for the call to SET_DISPLAY_VOLTAGE");
-
-
-/* protocol and display type defines */
-#define MAX_BRLVGER_CELLS 72
-#define MAX_INTERRUPT_DATA 8
-/* control message request types */
-#define BRLVGER_READ_REQ 0xC2
-#define BRLVGER_WRITE_REQ 0x42
-/* control message request codes */
-#define BRLVGER_SET_DISPLAY_ON 0
-#define BRLVGER_SET_DISPLAY_VOLTAGE 1
-#define BRLVGER_GET_SERIAL 3
-#define BRLVGER_GET_HWVERSION 4
-#define BRLVGER_GET_FWVERSION 5
-#define BRLVGER_GET_LENGTH 6
-#define BRLVGER_SEND_BRAILLE 7
-#define BRLVGER_BEEP 9
-#if 0 /* not used and not sure they're working */
-#define BRLVGER_GET_DISPLAY_VOLTAGE 2
-#define BRLVGER_GET_CURRENT 8
-#endif
-
-/* Prototypes */
-static int brlvger_probe (struct usb_interface *intf,
-                         const struct usb_device_id *id);
-static void brlvger_disconnect(struct usb_interface *intf);
-static int brlvger_open(struct inode *inode, struct file *file);
-static int brlvger_release(struct inode *inode, struct file *file);
-static ssize_t brlvger_write(struct file *file, const char __user *buffer,
-                            size_t count, loff_t *pos);
-static ssize_t brlvger_read(struct file *file, char __user *buffer,
-                           size_t count, loff_t *unused_pos);
-static int brlvger_ioctl(struct inode *inode, struct file *file,
-                        unsigned cmd, unsigned long arg);
-static unsigned brlvger_poll(struct file *file, poll_table *wait);
-static loff_t brlvger_llseek(struct file * file, loff_t offset, int orig);
-static void intr_callback(struct urb *urb, struct pt_regs *regs);
-struct brlvger_priv;
-static int brlvger_get_hw_version(struct brlvger_priv *priv,
-                                 unsigned char *verbuf);
-static int brlvger_get_fw_version(struct brlvger_priv *priv,
-                                 unsigned char *buf);
-static int brlvger_get_serial(struct brlvger_priv *priv,
-                             unsigned char *buf);
-static int brlvger_get_display_length(struct brlvger_priv *priv);
-static int brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on);
-static int brlvger_beep(struct brlvger_priv *priv, __u16 duration);
-static int brlvger_set_display_voltage(struct brlvger_priv *priv,
-                                      __u16 voltage);
-static int mycontrolmsg(const char *funcname,
-                        struct brlvger_priv *priv, unsigned pipe_dir,
-                        __u8 request, __u8 requesttype, __u16 value,
-                        __u16 index, void *data, __u16 size);
-
-#define controlmsg(priv,pipe_dir,a,b,c,d,e,f) \
-     mycontrolmsg(__FUNCTION__, priv, pipe_dir, \
-                  a,b,c,d,e,f)
-#define sndcontrolmsg(priv,a,b,c,d,e,f) \
-    controlmsg(priv, 0, a,b,c,d,e,f)
-#define rcvcontrolmsg(priv,a,b,c,d,e,f) \
-    controlmsg(priv, USB_DIR_IN, a,b,c,d,e,f)
-
-/* ----------------------------------------------------------------------- */
-
-/* Data */
-
-/* key event queue size */
-#define MAX_INTERRUPT_BUFFER 10
-
-/* private state */
-struct brlvger_priv {
-       struct usb_device   *dev; /* USB device handle */
-       struct usb_endpoint_descriptor *in_interrupt;
-       struct urb *intr_urb;
-
-       int subminor; /* which minor dev #? */
-
-       unsigned char hwver[BRLVGER_HWVER_SIZE]; /* hardware version */
-       unsigned char fwver[BRLVGER_FWVER_SIZE]; /* firmware version */
-       unsigned char serialnum[BRLVGER_SERIAL_SIZE];
-
-       int llength; /* logical length */
-       int plength; /* physical length */
-
-       __u8 obuf[MAX_BRLVGER_CELLS];
-       __u8 intr_buff[MAX_INTERRUPT_DATA];
-       __u8 event_queue[MAX_INTERRUPT_BUFFER][MAX_INTERRUPT_DATA];
-       atomic_t intr_idx, read_idx;
-       spinlock_t intr_idx_lock; /* protects intr_idx */
-       wait_queue_head_t read_wait;
-
-       int opened;
-       struct semaphore open_sem; /* protects ->opened */
-       struct semaphore dev_sem; /* protects ->dev */
-};
-
-/* Globals */
-
-/* For blocking open */
-static DECLARE_WAIT_QUEUE_HEAD(open_wait);
-
-/* Some print macros */
-#ifdef dbg
-#undef dbg
-#endif
-#ifdef info
-#undef info
-#endif
-#ifdef err
-#undef err
-#endif
-#define info(args...) \
-    ({ printk(KERN_INFO "Voyager: " args); \
-       printk("\n"); })
-#define err(args...) \
-    ({ printk(KERN_ERR "Voyager: " args); \
-       printk("\n"); })
-#define dbgprint(fmt, args...) \
-    ({ printk(KERN_DEBUG "Voyager: %s: " fmt, __FUNCTION__ , ##args); \
-       printk("\n"); })
-#define dbg(args...) \
-    ({ if(debug >= 1) dbgprint(args); })
-#define dbg2(args...) \
-    ({ if(debug >= 2) dbgprint(args); })
-#define dbg3(args...) \
-    ({ if(debug >= 3) dbgprint(args); })
-
-/* ----------------------------------------------------------------------- */
-
-/* Driver registration */
-
-static struct usb_device_id brlvger_ids [] = {
-       { USB_DEVICE(0x0798, 0x0001) },
-       { }                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, brlvger_ids);
-
-static struct file_operations brlvger_fops =
-{
-       .owner =        THIS_MODULE,
-       .llseek =       brlvger_llseek,
-       .read =         brlvger_read,
-       .write =        brlvger_write,
-       .ioctl =        brlvger_ioctl,
-       .open =         brlvger_open,
-       .release =      brlvger_release,
-       .poll =         brlvger_poll,
-};
-
-static struct usb_class_driver brlvger_class = {
-       .name =         "usb/brlvger%d",
-       .fops =         &brlvger_fops,
-       .mode =         S_IFCHR | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP,
-       .minor_base =   BRLVGER_MINOR,
-};
-
-static struct usb_driver brlvger_driver =
-{
-       .owner =        THIS_MODULE,
-       .name =         "brlvger",
-       .probe =        brlvger_probe,
-       .disconnect =   brlvger_disconnect,
-       .id_table =     brlvger_ids,
-};
-
-static int
-__init brlvger_init (void)
-{
-       int retval;
-       printk(BANNER);
-
-       if(stall_tries < 1 || write_repeats < 1)
-         return -EINVAL;
-
-       retval = usb_register(&brlvger_driver);
-       if (retval) {
-               err("USB registration failed");
-               goto out;
-       }
-
-out:
-       return retval;
-}
-
-static void
-__exit brlvger_cleanup (void)
-{
-       usb_deregister (&brlvger_driver);
-       dbg("Driver unregistered");
-}
-
-module_init (brlvger_init);
-module_exit (brlvger_cleanup);
-
-/* ----------------------------------------------------------------------- */
-
-/* Probe and disconnect functions */
-
-static int
-brlvger_probe (struct usb_interface *intf,
-              const struct usb_device_id *id)
-{
-       struct usb_device *dev = interface_to_usbdev(intf);
-       struct brlvger_priv *priv = NULL;
-       int retval;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_host_interface *actifsettings;
-       /* protects against reentrance: once we've found a free slot
-          we reserve it.*/
-       static DECLARE_MUTEX(reserve_sem);
-
-       actifsettings = dev->actconfig->interface[0]->altsetting;
-
-       if( dev->descriptor.bNumConfigurations != 1
-                       || dev->config->desc.bNumInterfaces != 1 
-                       || actifsettings->desc.bNumEndpoints != 1 ) {
-               err ("Bogus braille display config info");
-               return -ENODEV;
-       }
-
-       endpoint = &actifsettings->endpoint [0].desc;
-       if (!(endpoint->bEndpointAddress & 0x80) ||
-               ((endpoint->bmAttributes & 3) != 0x03)) {
-               err ("Bogus braille display config info, wrong endpoints");
-               return -ENODEV;
-       }
-
-       down(&reserve_sem);
-
-       retval = usb_register_dev(intf, &brlvger_class);
-       if (retval) {
-               err("Not able to get a minor for this device.");
-               goto error;
-       }
-
-       if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){
-               err("No more memory");
-               goto error;
-       }
-
-       memset(priv, 0, sizeof(*priv));
-       atomic_set(&priv->intr_idx, 0);
-       atomic_set(&priv->read_idx, MAX_INTERRUPT_BUFFER-1);
-       spin_lock_init(&priv->intr_idx_lock);
-       init_waitqueue_head(&priv->read_wait);
-       /* opened is memset'ed to 0 */
-       init_MUTEX(&priv->open_sem);
-       init_MUTEX(&priv->dev_sem);
-
-       priv->subminor = intf->minor;
-
-       /* we found a interrupt in endpoint */
-       priv->in_interrupt = endpoint;
-
-       priv->dev = dev;
-
-       if(brlvger_get_hw_version(priv, priv->hwver) <0) {
-               err("Unable to get hardware version");
-               goto error;
-       }
-       dbg("Hw ver %d.%d", priv->hwver[0], priv->hwver[1]);
-       if(brlvger_get_fw_version(priv, priv->fwver) <0) {
-               err("Unable to get firmware version");
-               goto error;
-       }
-       dbg("Fw ver: %s", priv->fwver);
-
-       if(brlvger_get_serial(priv, priv->serialnum) <0) {
-               err("Unable to get serial number");
-               goto error;
-       }
-       dbg("Serial number: %s", priv->serialnum);
-
-       if( (priv->llength = brlvger_get_display_length(priv)) <0 ){
-               err("Unable to get display length");
-               goto error;
-       }
-       switch(priv->llength) {
-       case 48:
-               priv->plength = 44;
-               break;
-       case 72:
-               priv->plength = 70;
-               break;
-       default:
-               err("Unsupported display length: %d", priv->llength);
-               goto error;
-       };
-       dbg("Display length: %d", priv->plength);
-
-       usb_set_intfdata (intf, priv);
-       info( "Braille display %d is device major %d minor %d",
-                               intf->minor, USB_MAJOR, BRLVGER_MINOR + intf->minor);
-
-       /* Tell anyone waiting on a blocking open */
-       wake_up_interruptible(&open_wait);
-
-       goto out;
-
- error:
-       if(priv) {
-               kfree( priv );
-               priv = NULL;
-       }
-
- out:
-       up(&reserve_sem);
-       if (priv) {
-               usb_set_intfdata (intf, priv);
-               return 0;
-       }
-       return -EIO;
-}
-
-static void
-brlvger_disconnect(struct usb_interface *intf)
-{
-       struct brlvger_priv *priv = usb_get_intfdata (intf);
-       int r;
-
-       usb_set_intfdata (intf, NULL);
-       if(priv){
-               info("Display %d disconnecting", priv->subminor);
-
-               usb_deregister_dev(intf, &brlvger_class);
-
-               down(&priv->open_sem);
-               down(&priv->dev_sem);
-               if(priv->opened) {
-                       /* Disable interrupts */
-                       if((r = usb_unlink_urb(priv->intr_urb)) <0)
-                               err("usb_unlink_urb returns %d", r);
-                       usb_free_urb(priv->intr_urb);
-                       /* mark device as dead and prevent control
-                          messages to it */
-                       priv->dev = NULL;
-                       /* Tell anyone hung up on a read that it
-                          won't be coming */
-                       wake_up_interruptible(&priv->read_wait);
-                       up(&priv->dev_sem);
-                       up(&priv->open_sem);
-               }else
-                       /* no corresponding up()s */
-                       kfree(priv);
-       }
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* fops implementation */
-
-static int
-brlvger_open(struct inode *inode, struct file *file)
-{
-       int devnum = iminor(inode);
-       struct usb_interface *intf = NULL;
-       struct brlvger_priv *priv = NULL;
-       int n, ret;
-
-       if (devnum < 0)
-               return -ENXIO;
-
-       n = devnum - BRLVGER_MINOR;
-
-       do {
-               intf = usb_find_interface(&brlvger_driver, devnum);
-               if (!intf) {
-                       if (file->f_flags & O_NONBLOCK) {
-                               dbg3("Failing non-blocking open: "
-                                    "device %d not connected", n);
-                               return -EAGAIN;
-                       }
-                       /* Blocking open. One global wait queue will
-                          suffice. We wait until a device for the selected
-                          minor is connected. */
-                       dbg2("Waiting for device %d to be connected", n);
-                       ret = wait_event_interruptible(open_wait,
-                                                      (intf = 
usb_find_interface(&brlvger_driver, devnum)));
-                       if (ret) {
-                               dbg2("Interrupted wait for device %d", n);
-                               return ret;
-                       }
-               }
-       } while(!intf);
-       priv = usb_get_intfdata(intf);
-
-       /* We grabbed an existing device. */
-       if(down_interruptible(&priv->open_sem))
-               return -ERESTARTSYS;
-
-       /* Only one process can open each device, no sharing. */
-       ret = -EBUSY;
-       if(priv->opened)
-               goto out;
-
-       dbg("Opening display %d", priv->subminor);
-
-       /* Setup interrupt handler for receiving key input */
-       priv->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if(!priv->intr_urb) {
-               err("Unable to allocate URB");
-               goto out;
-       }
-       usb_fill_int_urb( priv->intr_urb, priv->dev,
-                       usb_rcvintpipe(priv->dev,
-                                      priv->in_interrupt->bEndpointAddress),
-                       priv->intr_buff, sizeof(priv->intr_buff),
-                       intr_callback, priv, priv->in_interrupt->bInterval);
-       if((ret = usb_submit_urb(priv->intr_urb, GFP_KERNEL)) <0){
-               err("Error %d while submitting URB", ret);
-               goto out;
-       }
-
-       /* Set voltage */
-       if(brlvger_set_display_voltage(priv, raw_voltage) <0) {
-               err("Unable to set voltage");
-               goto out;
-       }
-
-       /* Turn display on */
-       if((ret = brlvger_set_display_on_off(priv, 1)) <0) {
-               err("Error %d while turning display on", ret);
-               goto out;
-       }
-
-       /* Mark as opened, so disconnect cannot free priv. */
-       priv->opened = 1;
-
-       file->private_data = priv;
-
-       ret = 0;
-       goto out;
-
- out:
-       up(&priv->open_sem);
-       return ret;
-}
-
-static int
-brlvger_release(struct inode *inode, struct file *file)
-{
-       struct brlvger_priv *priv = file->private_data;
-       int r;
-
-       /* Turn display off. Safe even if disconnected. */
-       brlvger_set_display_on_off(priv, 0);
-
-       /* mutex with disconnect and with open */
-       down(&priv->open_sem);
-
-       if(!priv->dev) {
-               dbg("Releasing disconnected device %d", priv->subminor);
-               /* no up(&priv->open_sem) */
-               kfree(priv);
-       }else{
-               dbg("Closing display %d", priv->subminor);
-               /* Disable interrupts */
-               if((r = usb_unlink_urb(priv->intr_urb)) <0)
-                       err("usb_unlink_urb returns %d", r);
-               usb_free_urb(priv->intr_urb);
-               priv->opened = 0;
-               up(&priv->open_sem);
-       }
-
-       return 0;
-}
-
-static ssize_t
-brlvger_write(struct file *file, const char __user *buffer,
-             size_t count, loff_t *pos)
-{
-       struct brlvger_priv *priv = file->private_data;
-       char buf[MAX_BRLVGER_CELLS];
-       int ret;
-       size_t rs;
-       loff_t off;
-       __u16 written;
-
-       if(!priv->dev)
-               return -ENOLINK;
-
-       off = *pos;
-
-       if(off > priv->plength)
-               return -ESPIPE;;
-
-       rs = priv->plength - off;
-
-       if(count > rs)
-               count = rs;
-       written = count;
-
-       if (copy_from_user (buf, buffer, count ) )
-               return -EFAULT;
-
-       memset(priv->obuf, 0xaa, sizeof(priv->obuf));
-
-       /* Firmware supports multiples of 8cells, so some cells are absent
-          and for some reason there actually are holes! euurkkk! */
-
-       if( priv->plength == 44 ) {
-               /* Two ghost cells at the beginning of the display, plus
-                  two more after the sixth physical cell. */
-               if(off > 5) {
-                       off +=4;
-                       memcpy(priv->obuf, buf, count);
-               }else{
-                       int firstpart = 6 - off;
-                       
-#ifdef WRITE_DEBUG
-                       dbg3("off: %lld, rs: %d, count: %d, firstpart: %d",
-                            off, rs, count, firstpart);
-#endif
-
-                       firstpart = (firstpart < count) ? firstpart : count;
-
-#ifdef WRITE_DEBUG
-                       dbg3("off: %lld", off);
-                       dbg3("firstpart: %d", firstpart);
-#endif
-
-                       memcpy(priv->obuf, buf, firstpart);
-
-                       if(firstpart != count) {
-                               int secondpart = count - firstpart;
-#ifdef WRITE_DEBUG
-                               dbg3("secondpart: %d", secondpart);
-#endif
-
-                               memcpy(priv->obuf+(firstpart+2),
-                                      buf+firstpart, secondpart);
-                               written +=2;
-                       }
-
-                       off +=2;
-
-#ifdef WRITE_DEBUG
-                       dbg3("off: %lld, rs: %d, count: %d, firstpart: %d, "
-                               "written: %d",  off, rs, count, firstpart, written);
-#endif
-               }
-       }else{
-               /* Two ghost cells at the beginningg of the display. */
-               memcpy(priv->obuf, buf, count);
-               off += 2;
-       }
-
-       {
-               int repeat = write_repeats;
-               /* Dirty hack: sometimes some of the dots are wrong and somehow
-                  right themselves if the command is repeated. */
-               while(repeat--) {
-                       ret = sndcontrolmsg(priv,
-                               BRLVGER_SEND_BRAILLE, BRLVGER_WRITE_REQ, 0,
-                               off, priv->obuf, written);
-                       if(ret <0)
-                               return ret;
-               }
-       }
-
-       return count;
-}
-
-static int
-read_index(struct brlvger_priv *priv)
-{
-       int intr_idx, read_idx;
-
-       read_idx = atomic_read(&priv->read_idx);
-       read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
-
-       intr_idx = atomic_read(&priv->intr_idx);
-
-       return(read_idx == intr_idx ? -1 : read_idx);
-}
-
-static ssize_t
-brlvger_read(struct file *file, char __user *buffer,
-            size_t count, loff_t *unused_pos)
-{
-       struct brlvger_priv *priv = file->private_data;
-       int read_idx;
-
-       if(count != MAX_INTERRUPT_DATA)
-               return -EINVAL;
-
-       if(!priv->dev)
-               return -ENOLINK;
-
-       if((read_idx = read_index(priv)) == -1) {
-               /* queue empty */
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               else{
-                       int r = wait_event_interruptible(priv->read_wait,
-                                                        (!priv->dev || (read_idx = 
read_index(priv)) != -1));
-                       if(!priv->dev)
-                               return -ENOLINK;
-                       if(r)
-                               return r;
-                       if(read_idx == -1)
-                               /* should not happen */
-                               return 0;
-               }
-       }
-
-       if (copy_to_user (buffer, priv->event_queue[read_idx], count) )
-               return( -EFAULT);
-
-       atomic_set(&priv->read_idx, read_idx);
-       /* Multiple opens are not allowed. Yet on SMP, two processes could
-          read at the same time (on a shared file descriptor); then it is not
-          deterministic whether or not they will get duplicates of a key
-          event. */
-       return MAX_INTERRUPT_DATA;
-}
-
-static int
-brlvger_ioctl(struct inode *inode, struct file *file,
-             unsigned cmd, unsigned long arg)
-{
-       struct brlvger_priv *priv = file->private_data;
-
-       if(!priv->dev)
-               return -ENOLINK;
-
-       switch(cmd) {
-       case BRLVGER_GET_INFO: {
-               struct brlvger_info vi;
-
-               memset(&vi, 0, sizeof(vi));
-               strlcpy(vi.driver_version, DRIVER_VERSION,
-                       sizeof(vi.driver_version));
-               strlcpy(vi.driver_banner, longbanner,
-                       sizeof(vi.driver_banner));
-
-               vi.display_length = priv->plength;
-               
-               memcpy(&vi.hwver, priv->hwver, BRLVGER_HWVER_SIZE);
-               memcpy(&vi.fwver, priv->fwver, BRLVGER_FWVER_SIZE);
-               memcpy(&vi.serialnum, priv->serialnum, BRLVGER_SERIAL_SIZE);
-
-               if(copy_to_user((void __user *)arg, &vi, sizeof(vi)))
-                       return -EFAULT;
-               return 0;
-       }
-       case BRLVGER_DISPLAY_ON:
-               return brlvger_set_display_on_off(priv, 1);
-       case BRLVGER_DISPLAY_OFF:
-               return brlvger_set_display_on_off(priv, 0);
-       case BRLVGER_BUZZ: {
-               __u16 duration;
-               if(get_user(duration, (__u16 *)arg))
-                       return -EFAULT;
-               return brlvger_beep(priv, duration);
-       }
-
-#if 0 /* Underlying commands don't seem to work for some reason; not clear if
-        we'd want to export these anyway. */
-       case BRLVGER_SET_VOLTAGE: {
-               __u16 voltage;
-               if(get_user(voltage, (__u16 *)arg))
-                       return -EFAULT;
-               return brlvger_set_display_voltage(priv, voltage);
-       }
-       case BRLVGER_GET_VOLTAGE: {
-               __u8 voltage;
-               int r = brlvger_get_display_voltage(priv);
-               if(r <0)
-                       return r;
-               voltage = r;
-               if(put_user(voltage, (__u8 *)arg))
-                       return -EFAULT;
-               return 0;
-       }
-#endif
-       default:
-               return -EINVAL;
-       };
-}
-
-static loff_t
-brlvger_llseek(struct file *file, loff_t offset, int orig)
-{
-       struct brlvger_priv *priv = file->private_data;
-
-       if(!priv->dev)
-               return -ENOLINK;
-
-       switch (orig) {
-               case 0:
-                       /*  nothing to do */
-                       break;
-               case 1:
-                       offset +=file->f_pos;
-                       break;
-               case 2:
-                       offset += priv->plength;
-               default:
-                       return -EINVAL;
-       }
-
-       if((offset >= priv->plength) || (offset < 0))
-               return -EINVAL;
-
-       return (file->f_pos = offset);
-}
-
-static unsigned
-brlvger_poll(struct file *file, poll_table *wait) 
-{
-       struct brlvger_priv *priv = file->private_data;
-
-       if(!priv->dev)
-               return POLLERR | POLLHUP;
-
-       poll_wait(file, &priv->read_wait, wait);
-
-       if(!priv->dev)
-               return POLLERR | POLLHUP;
-       if(read_index(priv) != -1)
-               return POLLIN | POLLRDNORM;
-
-       return 0;
-}
-
-static void
-intr_callback(struct urb *urb, struct pt_regs *regs)
-{
-       struct brlvger_priv *priv = urb->context;
-       int intr_idx, read_idx;
-       int status;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, 
urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       read_idx = atomic_read(&priv->read_idx);
-       spin_lock(&priv->intr_idx_lock);
-       intr_idx = atomic_read(&priv->intr_idx);
-       if(read_idx == intr_idx) {
-               dbg2("Queue full, dropping braille display input");
-               spin_unlock(&priv->intr_idx_lock);
-               goto exit;      /* queue full */
-       }
-
-       memcpy(priv->event_queue[intr_idx], urb->transfer_buffer,
-              MAX_INTERRUPT_DATA);
-
-       intr_idx = (++intr_idx == MAX_INTERRUPT_BUFFER)? 0 : intr_idx;
-       atomic_set(&priv->intr_idx, intr_idx);
-       spin_unlock(&priv->intr_idx_lock);
-
-       wake_up_interruptible(&priv->read_wait);
-
-exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* Hardware access functions */
-
-static int
-mycontrolmsg(const char *funcname,
-            struct brlvger_priv *priv, unsigned pipe_dir,
-            __u8 request, __u8 requesttype, __u16 value,
-            __u16 index, void *data, __u16 size)
-{
-       int ret=0, tries = stall_tries;
-
-       /* Make sure the device was not disconnected */
-       if(down_interruptible(&priv->dev_sem))
-               return -ERESTARTSYS;
-       if(!priv->dev) {
-               up(&priv->dev_sem);
-               return -ENOLINK;
-       }
-
-       /* Dirty hack for retransmission: stalls and fails all the time
-          without this on the hardware we tested. */
-       while(tries--) {
-               ret = usb_control_msg(priv->dev,
-                   usb_sndctrlpipe(priv->dev,0) |pipe_dir,
-                   request, requesttype, value,
-                   index, data, size,
-                   HZ);
-               if(ret != -EPIPE)
-                       break;
-               dbg2("Stalled, remaining %d tries", tries);
-       }
-       up(&priv->dev_sem);
-       if(ret <0) {
-               err("%s: usb_control_msg returns %d",
-                               funcname, ret);
-               return -EIO;
-       }
-       return 0;
-}
-
-static int
-brlvger_get_hw_version(struct brlvger_priv *priv, unsigned char *verbuf)
-{
-       return rcvcontrolmsg(priv,
-           BRLVGER_GET_HWVERSION, BRLVGER_READ_REQ, 0,
-           0, verbuf, BRLVGER_HWVER_SIZE);
-       /* verbuf should be 2 bytes */
-}
-
-static int
-brlvger_get_fw_version(struct brlvger_priv *priv, unsigned char *buf)
-{
-       unsigned char rawbuf[(BRLVGER_FWVER_SIZE-1)*2+2];
-       int i, len;
-       int r = rcvcontrolmsg(priv,
-                             BRLVGER_GET_FWVERSION, BRLVGER_READ_REQ, 0,
-                             0, rawbuf, sizeof(rawbuf));
-       if(r<0)
-               return r;
-
-       /* If I guess correctly: succession of 16bit words, the string is
-           formed of the first byte of each of these words. First byte in
-           buffer indicates total length of data; not sure what second byte is
-           for. */
-       len = rawbuf[0]-2;
-       if(len<0)
-               len = 0;
-       else if(len+1 > BRLVGER_FWVER_SIZE)
-               len = BRLVGER_FWVER_SIZE-1;
-       for(i=0; i<len; i++)
-               buf[i] = rawbuf[2+2*i];
-       buf[i] = 0;
-       return 0;
-}
-
-static int
-brlvger_get_serial(struct brlvger_priv *priv, unsigned char *buf)
-{
-       unsigned char rawserial[BRLVGER_SERIAL_BIN_SIZE];
-       int i;
-       int r = rcvcontrolmsg(priv,
-                             BRLVGER_GET_SERIAL, BRLVGER_READ_REQ, 0,
-                             0, rawserial, sizeof(rawserial));
-       if(r<0)
-               return r;
-
-       for(i=0; i<BRLVGER_SERIAL_BIN_SIZE; i++) {
-#define NUM_TO_HEX(n) (((n)>9) ? (n)+'A' : (n)+'0')
-               buf[2*i] = NUM_TO_HEX(rawserial[i] >>4);
-               buf[2*i+1] = NUM_TO_HEX(rawserial[i] &0xf);
-       }
-       buf[2*i] = 0;
-       return 0;
-}
-
-static int
-brlvger_get_display_length(struct brlvger_priv *priv)
-{
-       unsigned char data[2];
-       int ret = rcvcontrolmsg(priv,
-           BRLVGER_GET_LENGTH, BRLVGER_READ_REQ, 0,
-           0, data, 2);
-       if(ret<0)
-               return ret;
-       return data[1];
-}
-
-static int
-brlvger_beep(struct brlvger_priv *priv, __u16 duration)
-{
-       return sndcontrolmsg(priv,
-           BRLVGER_BEEP, BRLVGER_WRITE_REQ, duration,
-           0, NULL, 0);
-}
-
-static int
-brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on)
-{
-       dbg2("Turning display %s", ((on) ? "on" : "off"));
-       return sndcontrolmsg(priv,
-           BRLVGER_SET_DISPLAY_ON,     BRLVGER_WRITE_REQ, on,
-           0, NULL, 0);
-}
-
-static int
-brlvger_set_display_voltage(struct brlvger_priv *priv, __u16 voltage)
-{
-       dbg("SET_DISPLAY_VOLTAGE to %u", voltage);
-        return sndcontrolmsg(priv,
-            BRLVGER_SET_DISPLAY_VOLTAGE, BRLVGER_WRITE_REQ, voltage,
-            0, NULL, 0);
-}
-
-#if 0 /* Had problems testing these commands. Not particularly useful anyway.*/
-
-static int
-brlvger_get_display_voltage(struct brlvger_priv *priv)
-{
-       __u8 voltage = 0;
-       int ret = rcvcontrolmsg(priv,
-           BRLVGER_GET_DISPLAY_VOLTAGE, BRLVGER_READ_REQ, 0,
-           0, &voltage, 1);
-       if(ret<0)
-               return ret;
-       return voltage;
-}
-
-static int
-brlvger_get_current(struct brlvger_priv *priv)
-{
-       unsigned char data;
-       int ret = rcvcontrolmsg(priv,
-           BRLVGER_GET_CURRENT,        BRLVGER_READ_REQ,       0,
-           0, &data, 1);
-       if(ret<0)
-               return ret;
-       return data;
-}
-#endif
diff -Nru a/include/linux/brlvger.h b/include/linux/brlvger.h
--- a/include/linux/brlvger.h   Tue Mar 16 15:03:20 2004
+++ /dev/null   Wed Dec 31 16:00:00 1969
@@ -1,54 +0,0 @@
-/*
- *      Tieman Voyager braille display USB driver.
- *
- *      Copyright 2001-2002 Stephane Dalton <[EMAIL PROTECTED]>
- *                      and Stéphane Doyon  <[EMAIL PROTECTED]>
- *            Maintained by Stéphane Doyon  <[EMAIL PROTECTED]>.
- */
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _LINUX_BRLVGER_H
-#define _LINUX_BRLVGER_H
-
-/* Ioctl request codes */
-#define BRLVGER_GET_INFO       0
-#define BRLVGER_DISPLAY_ON     2
-#define BRLVGER_DISPLAY_OFF    3
-#define BRLVGER_BUZZ           4
-
-/* Base minor for the char devices */
-#define BRLVGER_MINOR          128
-
-/* Size of some fields */
-#define BRLVGER_HWVER_SIZE     2
-#define BRLVGER_FWVER_SIZE     200 /* arbitrary, a long string */
-#define BRLVGER_SERIAL_BIN_SIZE        8
-#define BRLVGER_SERIAL_SIZE    ((2*BRLVGER_SERIAL_BIN_SIZE)+1)
-
-struct brlvger_info {
-       __u8 driver_version[12];
-       __u8 driver_banner[200];
-
-       __u32 display_length;
-       /* All other char[] fields are strings except this one.
-          Hardware version: first byte is major, second byte is minor. */
-       __u8 hwver[BRLVGER_HWVER_SIZE];
-       __u8 fwver[BRLVGER_FWVER_SIZE];
-       __u8 serialnum[BRLVGER_SERIAL_SIZE];
-};
-
-#endif



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to