linux-old/drivers/usb/brlvger.c
<<
>>
Prefs
   1/*
   2 *      Tieman Voyager braille display USB driver.
   3 *
   4 *      Copyright 2001-2002 Stephane Dalton <sdalton@videotron.ca>
   5 *                      and Stéphane Doyon  <s.doyon@videotron.ca>
   6 *            Maintained by Stéphane Doyon  <s.doyon@videotron.ca>.
   7 */
   8/*
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or
  12 *  (at your option) any later version.
  13 *
  14 *  This program is distributed in the hope that it will be useful,
  15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *  GNU General Public License for more details.
  18 *
  19 *  You should have received a copy of the GNU General Public License
  20 *  along with this program; if not, write to the Free Software
  21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22 */
  23/* History:
  24 * 0.8 April 2002: Integration into the kernel tree.
  25 * 0.7 October 2001: First public release as a module, distributed with
  26 *     the BRLTTY package (beta versions around 2.99y).
  27 */
  28
  29#define DRIVER_VERSION "v0.8"
  30#define DATE "April 2002"
  31#define DRIVER_AUTHOR \
  32        "Stephane Dalton <sdalton@videotron.ca> " \
  33        "and Stéphane Doyon <s.doyon@videotron.ca>"
  34#define DRIVER_DESC "Tieman Voyager braille display USB driver for Linux 2.4"
  35#define DRIVER_SHORTDESC "Voyager"
  36
  37#define BANNER \
  38        KERN_INFO DRIVER_SHORTDESC " " DRIVER_VERSION " (" DATE ")\n" \
  39        KERN_INFO "   by " DRIVER_AUTHOR "\n"
  40
  41static const char longbanner[] = {
  42        DRIVER_DESC ", " DRIVER_VERSION " (" DATE "), by " DRIVER_AUTHOR
  43};
  44
  45#include <linux/module.h>
  46#include <linux/usb.h>
  47#include <linux/init.h>
  48#include <linux/slab.h>
  49#include <linux/sched.h>
  50#include <asm/uaccess.h>
  51#include <asm/atomic.h>
  52#include <linux/poll.h>
  53#include <linux/devfs_fs_kernel.h>
  54#include <linux/brlvger.h>
  55
  56MODULE_AUTHOR( DRIVER_AUTHOR );
  57MODULE_DESCRIPTION( DRIVER_DESC );
  58MODULE_LICENSE("GPL");
  59
  60/* Module parameters */
  61
  62static int debug = 1;
  63MODULE_PARM(debug, "i");
  64MODULE_PARM_DESC(debug, "Debug level, 0-3");
  65
  66static int write_repeats = 2;
  67MODULE_PARM(write_repeats, "i");
  68MODULE_PARM_DESC(write_repeats, "Hack: repetitions for command to "
  69                 "display braille pattern");
  70                 /* to get rid of weird extra dots (perhaps only on
  71                    early hardware versions?) */
  72
  73static int stall_tries = 3;
  74MODULE_PARM(stall_tries, "i");
  75MODULE_PARM_DESC(stall_tries, "Hack: retransmits of stalled USB "
  76                 "control messages");
  77                 /* broken early hardware versions? */
  78
  79#define BRLVGER_RAW_VOLTAGE 89
  80/* from 0->300V to 255->200V, we are told 265V is normal operating voltage,
  81   but we don't know the scale. Assuming it is linear. */
  82static int raw_voltage = BRLVGER_RAW_VOLTAGE;
  83MODULE_PARM(raw_voltage, "i");
  84MODULE_PARM_DESC(raw_voltage, "Parameter for the call to SET_DISPLAY_VOLTAGE");
  85
  86
  87/* protocol and display type defines */
  88#define MAX_BRLVGER_CELLS 72
  89#define MAX_INTERRUPT_DATA 8
  90/* control message request types */
  91#define BRLVGER_READ_REQ 0xC2
  92#define BRLVGER_WRITE_REQ 0x42
  93/* control message request codes */
  94#define BRLVGER_SET_DISPLAY_ON 0
  95#define BRLVGER_SET_DISPLAY_VOLTAGE 1
  96#define BRLVGER_GET_SERIAL 3
  97#define BRLVGER_GET_HWVERSION 4
  98#define BRLVGER_GET_FWVERSION 5
  99#define BRLVGER_GET_LENGTH 6
 100#define BRLVGER_SEND_BRAILLE 7
 101#define BRLVGER_BEEP 9
 102#if 0 /* not used and not sure they're working */
 103#define BRLVGER_GET_DISPLAY_VOLTAGE 2
 104#define BRLVGER_GET_CURRENT 8
 105#endif
 106
 107/* Prototypes */
 108static void *brlvger_probe (struct usb_device *dev, unsigned ifnum,
 109                            const struct usb_device_id *id);
 110static void brlvger_disconnect(struct usb_device *dev, void *ptr);
 111static int brlvger_open(struct inode *inode, struct file *file);
 112static int brlvger_release(struct inode *inode, struct file *file);
 113static ssize_t brlvger_write(struct file *file, const char *buffer,
 114                             size_t count, loff_t *pos);
 115static ssize_t brlvger_read(struct file *file, char *buffer,
 116                            size_t count, loff_t *unused_pos);
 117static int brlvger_ioctl(struct inode *inode, struct file *file,
 118                         unsigned cmd, unsigned long arg);
 119static unsigned brlvger_poll(struct file *file, poll_table *wait);
 120static loff_t brlvger_llseek(struct file * file, loff_t offset, int orig);
 121static void intr_callback(struct urb *urb);
 122struct brlvger_priv;
 123static int brlvger_get_hw_version(struct brlvger_priv *priv,
 124                                  unsigned char *verbuf);
 125static int brlvger_get_fw_version(struct brlvger_priv *priv,
 126                                  unsigned char *buf);
 127static int brlvger_get_serial(struct brlvger_priv *priv,
 128                              unsigned char *buf);
 129static int brlvger_get_display_length(struct brlvger_priv *priv);
 130static int brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on);
 131static int brlvger_beep(struct brlvger_priv *priv, __u16 duration);
 132static int brlvger_set_display_voltage(struct brlvger_priv *priv,
 133                                       __u16 voltage);
 134static int mycontrolmsg(const char *funcname,
 135                        struct brlvger_priv *priv, unsigned pipe_dir,
 136                        __u8 request, __u8 requesttype, __u16 value,
 137                        __u16 index, void *data, __u16 size);
 138
 139#define controlmsg(priv,pipe_dir,a,b,c,d,e,f) \
 140     mycontrolmsg(__FUNCTION__, priv, pipe_dir, \
 141                  a,b,c,d,e,f)
 142#define sndcontrolmsg(priv,a,b,c,d,e,f) \
 143    controlmsg(priv, 0, a,b,c,d,e,f)
 144#define rcvcontrolmsg(priv,a,b,c,d,e,f) \
 145    controlmsg(priv, USB_DIR_IN, a,b,c,d,e,f)
 146
 147extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
 148
 149/* ----------------------------------------------------------------------- */
 150
 151/* Data */
 152
 153/* key event queue size */
 154#define MAX_INTERRUPT_BUFFER 10
 155
 156/* private state */
 157struct brlvger_priv {
 158        struct usb_device   *dev; /* USB device handle */
 159        struct usb_endpoint_descriptor *in_interrupt;
 160        struct urb *intr_urb;
 161        devfs_handle_t devfs;
 162
 163        int subminor; /* which minor dev #? */
 164
 165        unsigned char hwver[BRLVGER_HWVER_SIZE]; /* hardware version */
 166        unsigned char fwver[BRLVGER_FWVER_SIZE]; /* firmware version */
 167        unsigned char serialnum[BRLVGER_SERIAL_SIZE];
 168
 169        int llength; /* logical length */
 170        int plength; /* physical length */
 171
 172        __u8 obuf[MAX_BRLVGER_CELLS];
 173        __u8 intr_buff[MAX_INTERRUPT_DATA];
 174        __u8 event_queue[MAX_INTERRUPT_BUFFER][MAX_INTERRUPT_DATA];
 175        atomic_t intr_idx, read_idx;
 176        spinlock_t intr_idx_lock; /* protects intr_idx */
 177        wait_queue_head_t read_wait;
 178
 179        int opened;
 180        struct semaphore open_sem; /* protects ->opened */
 181        struct semaphore dev_sem; /* protects ->dev */
 182};
 183
 184/* Globals */
 185
 186/* Table of connected devices, a different minor for each. */
 187static struct brlvger_priv *display_table[ MAX_NR_BRLVGER_DEVS ];
 188
 189/* Mutex for the operation of removing a device from display_table */
 190static DECLARE_MUTEX(disconnect_sem);
 191
 192/* For blocking open */
 193static DECLARE_WAIT_QUEUE_HEAD(open_wait);
 194
 195/* Some print macros */
 196#ifdef dbg
 197#undef dbg
 198#endif
 199#ifdef info
 200#undef info
 201#endif
 202#ifdef err
 203#undef err
 204#endif
 205#define info(args...) \
 206    ({ printk(KERN_INFO "Voyager: " args); \
 207       printk("\n"); })
 208#define err(args...) \
 209    ({ printk(KERN_ERR "Voyager: " args); \
 210       printk("\n"); })
 211#define dbgprint(fmt, args...) \
 212    ({ printk(KERN_DEBUG "Voyager: %s: " fmt, __FUNCTION__ , ##args); \
 213       printk("\n"); })
 214#define dbg(args...) \
 215    ({ if(debug >= 1) dbgprint(args); })
 216#define dbg2(args...) \
 217    ({ if(debug >= 2) dbgprint(args); })
 218#define dbg3(args...) \
 219    ({ if(debug >= 3) dbgprint(args); })
 220
 221/* ----------------------------------------------------------------------- */
 222
 223/* Driver registration */
 224
 225static struct usb_device_id brlvger_ids [] = {
 226        { USB_DEVICE(0x0798, 0x0001) },
 227        { }                     /* Terminating entry */
 228};
 229MODULE_DEVICE_TABLE (usb, brlvger_ids);
 230
 231static struct file_operations brlvger_fops =
 232{
 233        owner:          THIS_MODULE,
 234        llseek:         brlvger_llseek,
 235        read:           brlvger_read,
 236        write:          brlvger_write,
 237        ioctl:          brlvger_ioctl,
 238        open:           brlvger_open,
 239        release:        brlvger_release,
 240        poll:           brlvger_poll,
 241};
 242
 243static struct usb_driver brlvger_driver =
 244{
 245        name:           "brlvger",
 246        probe:          brlvger_probe,
 247        disconnect:     brlvger_disconnect,
 248        fops:           &brlvger_fops,
 249        minor:          BRLVGER_MINOR,
 250        id_table:       brlvger_ids,
 251};
 252
 253static int
 254__init brlvger_init (void)
 255{
 256        printk(BANNER);
 257
 258        if(stall_tries < 1 || write_repeats < 1)
 259          return -EINVAL;
 260
 261        memset(display_table, 0, sizeof(display_table));
 262
 263        if (usb_register(&brlvger_driver)) {
 264                err("USB registration failed");
 265                return -ENOSYS;
 266        }
 267
 268        return 0;
 269}
 270
 271static void
 272__exit brlvger_cleanup (void)
 273{
 274        usb_deregister (&brlvger_driver);
 275        dbg("Driver unregistered");
 276}
 277
 278module_init (brlvger_init);
 279module_exit (brlvger_cleanup);
 280
 281/* ----------------------------------------------------------------------- */
 282
 283/* Probe and disconnect functions */
 284
 285static void *
 286brlvger_probe (struct usb_device *dev, unsigned ifnum,
 287               const struct usb_device_id *id)
 288{
 289        struct brlvger_priv *priv = NULL;
 290        int i;
 291        struct usb_endpoint_descriptor *endpoint;
 292        struct usb_interface_descriptor *actifsettings;
 293        /* protects against reentrance: once we've found a free slot
 294           we reserve it.*/
 295        static DECLARE_MUTEX(reserve_sem);
 296        char devfs_name[16];
 297
 298        actifsettings = dev->actconfig->interface->altsetting;
 299
 300        if( dev->descriptor.bNumConfigurations != 1
 301                        || dev->config->bNumInterfaces != 1 
 302                        || actifsettings->bNumEndpoints != 1 ) {
 303                err ("Bogus braille display config info");
 304                return NULL;
 305        }
 306
 307        endpoint = actifsettings->endpoint;
 308        if (!(endpoint->bEndpointAddress & 0x80) ||
 309                ((endpoint->bmAttributes & 3) != 0x03)) {
 310                err ("Bogus braille display config info, wrong endpoints");
 311                return NULL;
 312        }
 313
 314        down(&reserve_sem);
 315
 316        for( i = 0; i < MAX_NR_BRLVGER_DEVS; i++ )
 317                if( display_table[i] == NULL )
 318                        break;
 319
 320        if( i == MAX_NR_BRLVGER_DEVS ) {
 321                err( "This driver cannot handle more than %d "
 322                                "braille displays", MAX_NR_BRLVGER_DEVS);
 323                goto error;
 324        }
 325
 326        if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){
 327                err("No more memory");
 328                goto error;
 329        }
 330
 331        memset(priv, 0, sizeof(*priv));
 332        atomic_set(&priv->intr_idx, 0);
 333        atomic_set(&priv->read_idx, MAX_INTERRUPT_BUFFER-1);
 334        spin_lock_init(&priv->intr_idx_lock);
 335        init_waitqueue_head(&priv->read_wait);
 336        /* opened is memset'ed to 0 */
 337        init_MUTEX(&priv->open_sem);
 338        init_MUTEX(&priv->dev_sem);
 339
 340        priv->subminor = i;
 341
 342        /* we found a interrupt in endpoint */
 343        priv->in_interrupt = endpoint;
 344
 345        priv->dev = dev;
 346
 347        if(brlvger_get_hw_version(priv, priv->hwver) <0) {
 348                err("Unable to get hardware version");
 349                goto error;
 350        }
 351        dbg("Hw ver %d.%d", priv->hwver[0], priv->hwver[1]);
 352        if(brlvger_get_fw_version(priv, priv->fwver) <0) {
 353                err("Unable to get firmware version");
 354                goto error;
 355        }
 356        dbg("Fw ver: %s", priv->fwver);
 357
 358        if(brlvger_get_serial(priv, priv->serialnum) <0) {
 359                err("Unable to get serial number");
 360                goto error;
 361        }
 362        dbg("Serial number: %s", priv->serialnum);
 363
 364        if( (priv->llength = brlvger_get_display_length(priv)) <0 ){
 365                err("Unable to get display length");
 366                goto error;
 367        }
 368        switch(priv->llength) {
 369        case 48:
 370                priv->plength = 44;
 371                break;
 372        case 72:
 373                priv->plength = 70;
 374                break;
 375        default:
 376                err("Unsupported display length: %d", priv->llength);
 377                goto error;
 378        };
 379        dbg("Display length: %d", priv->plength);
 380
 381        sprintf(devfs_name, "brlvger%d", priv->subminor);
 382        priv->devfs = devfs_register(usb_devfs_handle, devfs_name,
 383                                     DEVFS_FL_DEFAULT, USB_MAJOR,
 384                                     BRLVGER_MINOR+priv->subminor,
 385                                     S_IFCHR |S_IRUSR|S_IWUSR |S_IRGRP|S_IWGRP,
 386                                     &brlvger_fops, NULL);
 387        if (!priv->devfs) {
 388#ifdef CONFIG_DEVFS_FS
 389                err("devfs node registration failed");
 390#endif
 391        }
 392
 393        display_table[i] = priv;
 394
 395        info( "Braille display %d is device major %d minor %d",
 396                                i, USB_MAJOR, BRLVGER_MINOR + i);
 397
 398        /* Tell anyone waiting on a blocking open */
 399        wake_up_interruptible(&open_wait);
 400
 401        goto out;
 402
 403 error:
 404        if(priv) {
 405                kfree( priv );
 406                priv = NULL;
 407        }
 408
 409 out:
 410        up(&reserve_sem);
 411        return priv;
 412}
 413
 414static void
 415brlvger_disconnect(struct usb_device *dev, void *ptr)
 416{
 417        struct brlvger_priv *priv = (struct brlvger_priv *)ptr;
 418        int r;
 419
 420        if(priv){
 421                info("Display %d disconnecting", priv->subminor);
 422
 423                devfs_unregister(priv->devfs);
 424                
 425                down(&disconnect_sem);
 426                display_table[priv->subminor] = NULL;
 427                up(&disconnect_sem);
 428
 429                down(&priv->open_sem);
 430                down(&priv->dev_sem);
 431                if(priv->opened) {
 432                        /* Disable interrupts */
 433                        if((r = usb_unlink_urb(priv->intr_urb)) <0)
 434                                err("usb_unlink_urb returns %d", r);
 435                        usb_free_urb(priv->intr_urb);
 436                        /* mark device as dead and prevent control
 437                           messages to it */
 438                        priv->dev = NULL;
 439                        /* Tell anyone hung up on a read that it
 440                           won't be coming */
 441                        wake_up_interruptible(&priv->read_wait);
 442                        up(&priv->dev_sem);
 443                        up(&priv->open_sem);
 444                }else
 445                        /* no corresponding up()s */
 446                        kfree(priv);
 447        }
 448}
 449
 450/* ----------------------------------------------------------------------- */
 451
 452/* fops implementation */
 453
 454static int
 455brlvger_open(struct inode *inode, struct file *file)
 456{
 457        int devnum = MINOR (inode->i_rdev);
 458        struct brlvger_priv *priv;
 459        int n, ret;
 460
 461        if (devnum < BRLVGER_MINOR
 462            || devnum >= (BRLVGER_MINOR + MAX_NR_BRLVGER_DEVS))
 463                return -ENXIO;
 464
 465        n = devnum - BRLVGER_MINOR;
 466
 467        MOD_INC_USE_COUNT;
 468
 469        do {
 470                down(&disconnect_sem);
 471                priv = display_table[n];
 472                
 473                if(!priv) {
 474                        up(&disconnect_sem);
 475                        if (file->f_flags & O_NONBLOCK) {
 476                                dbg3("Failing non-blocking open: "
 477                                     "device %d not connected", n);
 478                                MOD_DEC_USE_COUNT;
 479                                return -EAGAIN;
 480                        }
 481                        /* Blocking open. One global wait queue will
 482                           suffice. We wait until a device for the selected
 483                           minor is connected. */
 484                        dbg2("Waiting for device %d to be connected", n);
 485                        ret = wait_event_interruptible(open_wait,
 486                                                       display_table[n]
 487                                                       != NULL);
 488                        if(ret) {
 489                                dbg2("Interrupted wait for device %d", n);
 490                                MOD_DEC_USE_COUNT;
 491                                return ret;
 492                        }
 493                }
 494        } while(!priv);
 495        /* We grabbed an existing device. */
 496
 497        if(down_interruptible(&priv->open_sem))
 498                return -ERESTARTSYS;
 499        up(&disconnect_sem);
 500
 501        /* Only one process can open each device, no sharing. */
 502        ret = -EBUSY;
 503        if(priv->opened)
 504                goto error;
 505
 506        dbg("Opening display %d", priv->subminor);
 507
 508        /* Setup interrupt handler for receiving key input */
 509        priv->intr_urb = usb_alloc_urb(0);
 510        if(!priv->intr_urb) {
 511                err("Unable to allocate URB");
 512                goto error;
 513        }
 514        FILL_INT_URB( priv->intr_urb, priv->dev,
 515                        usb_rcvintpipe(priv->dev,
 516                                       priv->in_interrupt->bEndpointAddress),
 517                        priv->intr_buff, sizeof(priv->intr_buff),
 518                        intr_callback, priv, priv->in_interrupt->bInterval);
 519        if((ret = usb_submit_urb(priv->intr_urb)) <0){
 520                err("Error %d while submitting URB", ret);
 521                goto error;
 522        }
 523
 524        /* Set voltage */
 525        if(brlvger_set_display_voltage(priv, raw_voltage) <0) {
 526                err("Unable to set voltage");
 527                goto error;
 528        }
 529
 530        /* Turn display on */
 531        if((ret = brlvger_set_display_on_off(priv, 1)) <0) {
 532                err("Error %d while turning display on", ret);
 533                goto error;
 534        }
 535
 536        /* Mark as opened, so disconnect cannot free priv. */
 537        priv->opened = 1;
 538
 539        file->private_data = priv;
 540
 541        ret = 0;
 542        goto out;
 543
 544 error:
 545        MOD_DEC_USE_COUNT;
 546 out:
 547        up(&priv->open_sem);
 548        return ret;
 549}
 550
 551static int
 552brlvger_release(struct inode *inode, struct file *file)
 553{
 554        struct brlvger_priv *priv = file->private_data;
 555        int r;
 556
 557        /* Turn display off. Safe even if disconnected. */
 558        brlvger_set_display_on_off(priv, 0);
 559
 560        /* mutex with disconnect and with open */
 561        down(&priv->open_sem);
 562
 563        if(!priv->dev) {
 564                dbg("Releasing disconnected device %d", priv->subminor);
 565                /* no up(&priv->open_sem) */
 566                kfree(priv);
 567        }else{
 568                dbg("Closing display %d", priv->subminor);
 569                /* Disable interrupts */
 570                if((r = usb_unlink_urb(priv->intr_urb)) <0)
 571                        err("usb_unlink_urb returns %d", r);
 572                usb_free_urb(priv->intr_urb);
 573                priv->opened = 0;
 574                up(&priv->open_sem);
 575        }
 576
 577        MOD_DEC_USE_COUNT;
 578
 579        return 0;
 580}
 581
 582static ssize_t
 583brlvger_write(struct file *file, const char *buffer,
 584              size_t count, loff_t *pos)
 585{
 586        struct brlvger_priv *priv = file->private_data;
 587        char buf[MAX_BRLVGER_CELLS];
 588        int ret;
 589        size_t rs;
 590        loff_t off;
 591
 592        __u16 written;
 593
 594        if(!priv->dev)
 595                return -ENOLINK;
 596
 597        off = *pos;
 598
 599        if (off < 0)
 600                return -EINVAL;
 601
 602        if(off > priv->plength)
 603                return -ESPIPE;;
 604
 605        rs = priv->plength - off;
 606
 607        if(count > rs)
 608                count = rs;
 609        written = count;
 610
 611        if (copy_from_user (buf, buffer, count ) )
 612                return -EFAULT;
 613
 614        memset(priv->obuf, 0xaa, sizeof(priv->obuf));
 615
 616        /* Firmware supports multiples of 8cells, so some cells are absent
 617           and for some reason there actually are holes! euurkkk! */
 618
 619        if( priv->plength == 44 ) {
 620                /* Two ghost cells at the beginning of the display, plus
 621                   two more after the sixth physical cell. */
 622                if(off > 5) {
 623                        off +=4;
 624                        memcpy(priv->obuf, buf, count);
 625                }else{
 626                        int firstpart = 6 - off;
 627                        
 628#ifdef WRITE_DEBUG
 629                        dbg3("off: %lld, rs: %d, count: %d, firstpart: %d",
 630                             off, rs, count, firstpart);
 631#endif
 632
 633                        firstpart = (firstpart < count) ? firstpart : count;
 634
 635#ifdef WRITE_DEBUG
 636                        dbg3("off: %lld", off);
 637                        dbg3("firstpart: %d", firstpart);
 638#endif
 639
 640                        memcpy(priv->obuf, buf, firstpart);
 641
 642                        if(firstpart != count) {
 643                                int secondpart = count - firstpart;
 644#ifdef WRITE_DEBUG
 645                                dbg3("secondpart: %d", secondpart);
 646#endif
 647
 648                                memcpy(priv->obuf+(firstpart+2),
 649                                       buf+firstpart, secondpart);
 650                                written +=2;
 651                        }
 652
 653                        off +=2;
 654
 655#ifdef WRITE_DEBUG
 656                        dbg3("off: %lld, rs: %d, count: %d, firstpart: %d, "
 657                                "written: %d",  off, rs, count, firstpart, written);
 658#endif
 659                }
 660        }else{
 661                /* Two ghost cells at the beginningg of the display. */
 662                memcpy(priv->obuf, buf, count);
 663                off += 2;
 664        }
 665
 666        {
 667                int repeat = write_repeats;
 668                /* Dirty hack: sometimes some of the dots are wrong and somehow
 669                   right themselves if the command is repeated. */
 670                while(repeat--) {
 671                        ret = sndcontrolmsg(priv,
 672                                BRLVGER_SEND_BRAILLE, BRLVGER_WRITE_REQ, 0,
 673                                off, priv->obuf, written);
 674                        if(ret <0)
 675                                return ret;
 676                }
 677        }
 678
 679        return count;
 680}
 681
 682static int
 683read_index(struct brlvger_priv *priv)
 684{
 685        int intr_idx, read_idx;
 686
 687        read_idx = atomic_read(&priv->read_idx);
 688        read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
 689
 690        intr_idx = atomic_read(&priv->intr_idx);
 691
 692        return(read_idx == intr_idx ? -1 : read_idx);
 693}
 694
 695static ssize_t
 696brlvger_read(struct file *file, char *buffer,
 697             size_t count, loff_t *unused_pos)
 698{
 699        struct brlvger_priv *priv = file->private_data;
 700        int read_idx;
 701
 702        if(count != MAX_INTERRUPT_DATA)
 703                return -EINVAL;
 704
 705        if(!priv->dev)
 706                return -ENOLINK;
 707
 708        if((read_idx = read_index(priv)) == -1) {
 709                /* queue empty */
 710                if (file->f_flags & O_NONBLOCK)
 711                        return -EAGAIN;
 712                else{
 713                        int r = wait_event_interruptible(priv->read_wait,
 714                                                         (!priv->dev || (read_idx = read_index(priv)) != -1));
 715                        if(!priv->dev)
 716                                return -ENOLINK;
 717                        if(r)
 718                                return r;
 719                        if(read_idx == -1)
 720                                /* should not happen */
 721                                return 0;
 722                }
 723        }
 724
 725        if (copy_to_user (buffer, priv->event_queue[read_idx], count) )
 726                return( -EFAULT);
 727
 728        atomic_set(&priv->read_idx, read_idx);
 729        /* Multiple opens are not allowed. Yet on SMP, two processes could
 730           read at the same time (on a shared file descriptor); then it is not
 731           deterministic whether or not they will get duplicates of a key
 732           event. */
 733        return MAX_INTERRUPT_DATA;
 734}
 735
 736static int
 737brlvger_ioctl(struct inode *inode, struct file *file,
 738              unsigned cmd, unsigned long arg)
 739{
 740        struct brlvger_priv *priv = file->private_data;
 741
 742        if(!priv->dev)
 743                return -ENOLINK;
 744
 745        switch(cmd) {
 746        case BRLVGER_GET_INFO: {
 747                struct brlvger_info vi;
 748
 749                memset(&vi, 0, sizeof(vi));
 750                strncpy(vi.driver_version, DRIVER_VERSION,
 751                        sizeof(vi.driver_version));
 752                vi.driver_version[sizeof(vi.driver_version)-1] = 0;
 753                strncpy(vi.driver_banner, longbanner,
 754                        sizeof(vi.driver_banner));
 755                vi.driver_banner[sizeof(vi.driver_banner)-1] = 0;
 756
 757                vi.display_length = priv->plength;
 758                
 759                memcpy(&vi.hwver, priv->hwver, BRLVGER_HWVER_SIZE);
 760                memcpy(&vi.fwver, priv->fwver, BRLVGER_FWVER_SIZE);
 761                memcpy(&vi.serialnum, priv->serialnum, BRLVGER_SERIAL_SIZE);
 762
 763                if(copy_to_user((void *)arg, &vi, sizeof(vi)))
 764                        return -EFAULT;
 765                return 0;
 766        }
 767        case BRLVGER_DISPLAY_ON:
 768                return brlvger_set_display_on_off(priv, 1);
 769        case BRLVGER_DISPLAY_OFF:
 770                return brlvger_set_display_on_off(priv, 0);
 771        case BRLVGER_BUZZ: {
 772                __u16 duration;
 773                if(get_user(duration, (__u16 *)arg))
 774                        return -EFAULT;
 775                return brlvger_beep(priv, duration);
 776        }
 777
 778#if 0 /* Underlying commands don't seem to work for some reason; not clear if
 779         we'd want to export these anyway. */
 780        case BRLVGER_SET_VOLTAGE: {
 781                __u16 voltage;
 782                if(get_user(voltage, (__u16 *)arg))
 783                        return -EFAULT;
 784                return brlvger_set_display_voltage(priv, voltage);
 785        }
 786        case BRLVGER_GET_VOLTAGE: {
 787                __u8 voltage;
 788                int r = brlvger_get_display_voltage(priv);
 789                if(r <0)
 790                        return r;
 791                voltage = r;
 792                if(put_user(voltage, (__u8 *)arg))
 793                        return -EFAULT;
 794                return 0;
 795        }
 796#endif
 797        default:
 798                return -EINVAL;
 799        };
 800}
 801
 802static loff_t
 803brlvger_llseek(struct file *file, loff_t offset, int orig)
 804{
 805        struct brlvger_priv *priv = file->private_data;
 806
 807        if(!priv->dev)
 808                return -ENOLINK;
 809
 810        switch (orig) {
 811                case 0:
 812                        /*  nothing to do */
 813                        break;
 814                case 1:
 815                        offset +=file->f_pos;
 816                        break;
 817                case 2:
 818                        offset += priv->plength;
 819                default:
 820                        return -EINVAL;
 821        }
 822
 823        if((offset >= priv->plength) || (offset < 0))
 824                return -EINVAL;
 825
 826        return (file->f_pos = offset);
 827}
 828
 829static unsigned
 830brlvger_poll(struct file *file, poll_table *wait) 
 831{
 832        struct brlvger_priv *priv = file->private_data;
 833
 834        if(!priv->dev)
 835                return POLLERR | POLLHUP;
 836
 837        poll_wait(file, &priv->read_wait, wait);
 838
 839        if(!priv->dev)
 840                return POLLERR | POLLHUP;
 841        if(read_index(priv) != -1)
 842                return POLLIN | POLLRDNORM;
 843
 844        return 0;
 845}
 846
 847static void
 848intr_callback(struct urb *urb)
 849{
 850        struct brlvger_priv *priv = urb->context;
 851        int intr_idx, read_idx;
 852
 853        if( urb->status ) {
 854                if(urb->status == -ETIMEDOUT)
 855                        dbg2("Status -ETIMEDOUT, "
 856                             "probably disconnected");
 857                else if(urb->status != -ENOENT)
 858                        err("Status: %d", urb->status);
 859                return;
 860        }
 861
 862        read_idx = atomic_read(&priv->read_idx);
 863        spin_lock(&priv->intr_idx_lock);
 864        intr_idx = atomic_read(&priv->intr_idx);
 865        if(read_idx == intr_idx) {
 866                dbg2("Queue full, dropping braille display input");
 867                spin_unlock(&priv->intr_idx_lock);
 868                return; /* queue full */
 869        }
 870
 871        memcpy(priv->event_queue[intr_idx], urb->transfer_buffer,
 872               MAX_INTERRUPT_DATA);
 873
 874        intr_idx = (++intr_idx == MAX_INTERRUPT_BUFFER)? 0 : intr_idx;
 875        atomic_set(&priv->intr_idx, intr_idx);
 876        spin_unlock(&priv->intr_idx_lock);
 877
 878        wake_up_interruptible(&priv->read_wait);
 879}
 880
 881/* ----------------------------------------------------------------------- */
 882
 883/* Hardware access functions */
 884
 885static int
 886mycontrolmsg(const char *funcname,
 887             struct brlvger_priv *priv, unsigned pipe_dir,
 888             __u8 request, __u8 requesttype, __u16 value,
 889             __u16 index, void *data, __u16 size)
 890{
 891        int ret=0, tries = stall_tries;
 892
 893        /* Make sure the device was not disconnected */
 894        if(down_interruptible(&priv->dev_sem))
 895                return -ERESTARTSYS;
 896        if(!priv->dev) {
 897                up(&priv->dev_sem);
 898                return -ENOLINK;
 899        }
 900
 901        /* Dirty hack for retransmission: stalls and fails all the time
 902           without this on the hardware we tested. */
 903        while(tries--) {
 904                ret = usb_control_msg(priv->dev,
 905                    usb_sndctrlpipe(priv->dev,0) |pipe_dir,
 906                    request, requesttype, value,
 907                    index, data, size,
 908                    HZ);
 909                if(ret != -EPIPE)
 910                        break;
 911                dbg2("Stalled, remaining %d tries", tries);
 912        }
 913        up(&priv->dev_sem);
 914        if(ret <0) {
 915                err("%s: usb_control_msg returns %d",
 916                                funcname, ret);
 917                return -EIO;
 918        }
 919        return 0;
 920}
 921
 922static int
 923brlvger_get_hw_version(struct brlvger_priv *priv, unsigned char *verbuf)
 924{
 925        return rcvcontrolmsg(priv,
 926            BRLVGER_GET_HWVERSION, BRLVGER_READ_REQ, 0,
 927            0, verbuf, BRLVGER_HWVER_SIZE);
 928        /* verbuf should be 2 bytes */
 929}
 930
 931static int
 932brlvger_get_fw_version(struct brlvger_priv *priv, unsigned char *buf)
 933{
 934        unsigned char rawbuf[(BRLVGER_FWVER_SIZE-1)*2+2];
 935        int i, len;
 936        int r = rcvcontrolmsg(priv,
 937                              BRLVGER_GET_FWVERSION, BRLVGER_READ_REQ, 0,
 938                              0, rawbuf, sizeof(rawbuf));
 939        if(r<0)
 940                return r;
 941
 942        /* If I guess correctly: succession of 16bit words, the string is
 943           formed of the first byte of each of these words. First byte in
 944           buffer indicates total length of data; not sure what second byte is
 945           for. */
 946        len = rawbuf[0]-2;
 947        if(len<0)
 948                len = 0;
 949        else if(len+1 > BRLVGER_FWVER_SIZE)
 950                len = BRLVGER_FWVER_SIZE-1;
 951        for(i=0; i<len; i++)
 952                buf[i] = rawbuf[2+2*i];
 953        buf[i] = 0;
 954        return 0;
 955}
 956
 957static int
 958brlvger_get_serial(struct brlvger_priv *priv, unsigned char *buf)
 959{
 960        unsigned char rawserial[BRLVGER_SERIAL_BIN_SIZE];
 961        int i;
 962        int r = rcvcontrolmsg(priv,
 963                              BRLVGER_GET_SERIAL, BRLVGER_READ_REQ, 0,
 964                              0, rawserial, sizeof(rawserial));
 965        if(r<0)
 966                return r;
 967
 968        for(i=0; i<BRLVGER_SERIAL_BIN_SIZE; i++) {
 969#define NUM_TO_HEX(n) (((n)>9) ? (n)+'A' : (n)+'0')
 970                buf[2*i] = NUM_TO_HEX(rawserial[i] >>4);
 971                buf[2*i+1] = NUM_TO_HEX(rawserial[i] &0xf);
 972        }
 973        buf[2*i] = 0;
 974        return 0;
 975}
 976
 977static int
 978brlvger_get_display_length(struct brlvger_priv *priv)
 979{
 980        unsigned char data[2];
 981        int ret = rcvcontrolmsg(priv,
 982            BRLVGER_GET_LENGTH, BRLVGER_READ_REQ, 0,
 983            0, data, 2);
 984        if(ret<0)
 985                return ret;
 986        return data[1];
 987}
 988
 989static int
 990brlvger_beep(struct brlvger_priv *priv, __u16 duration)
 991{
 992        return sndcontrolmsg(priv,
 993            BRLVGER_BEEP, BRLVGER_WRITE_REQ, duration,
 994            0, NULL, 0);
 995}
 996
 997static int
 998brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on)
 999{
1000        dbg2("Turning display %s", ((on) ? "on" : "off"));
1001        return sndcontrolmsg(priv,
1002            BRLVGER_SET_DISPLAY_ON,     BRLVGER_WRITE_REQ, on,
1003            0, NULL, 0);
1004}
1005
1006static int
1007brlvger_set_display_voltage(struct brlvger_priv *priv, __u16 voltage)
1008{
1009        dbg("SET_DISPLAY_VOLTAGE to %u", voltage);
1010        return sndcontrolmsg(priv,
1011             BRLVGER_SET_DISPLAY_VOLTAGE, BRLVGER_WRITE_REQ, voltage,
1012             0, NULL, 0);
1013}
1014
1015#if 0 /* Had problems testing these commands. Not particularly useful anyway.*/
1016
1017static int
1018brlvger_get_display_voltage(struct brlvger_priv *priv)
1019{
1020        __u8 voltage = 0;
1021        int ret = rcvcontrolmsg(priv,
1022            BRLVGER_GET_DISPLAY_VOLTAGE, BRLVGER_READ_REQ, 0,
1023            0, &voltage, 1);
1024        if(ret<0)
1025                return ret;
1026        return voltage;
1027}
1028
1029static int
1030brlvger_get_current(struct brlvger_priv *priv)
1031{
1032        unsigned char data;
1033        int ret = rcvcontrolmsg(priv,
1034            BRLVGER_GET_CURRENT,        BRLVGER_READ_REQ,       0,
1035            0, &data, 1);
1036        if(ret<0)
1037                return ret;
1038        return data;
1039}
1040#endif
1041
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.