linux/drivers/usb/serial/empeg.c
<<
>>
Prefs
   1/*
   2 * USB Empeg empeg-car player driver
   3 *
   4 *      Copyright (C) 2000, 2001
   5 *          Gary Brubaker (xavyer@ix.netcom.com)
   6 *
   7 *      Copyright (C) 1999 - 2001
   8 *          Greg Kroah-Hartman (greg@kroah.com)
   9 *
  10 *      This program is free software; you can redistribute it and/or modify
  11 *      it under the terms of the GNU General Public License, as published by
  12 *      the Free Software Foundation, version 2.
  13 *
  14 * See Documentation/usb/usb-serial.txt for more information on using this
  15 * driver
  16 *
  17 * (07/16/2001) gb
  18 *      remove unused code in empeg_close() (thanks to Oliver Neukum for
  19 *      pointing this out) and rewrote empeg_set_termios().
  20 *
  21 * (05/30/2001) gkh
  22 *      switched from using spinlock to a semaphore, which fixes lots of
  23 * problems.
  24 *
  25 * (04/08/2001) gb
  26 *      Identify version on module load.
  27 *
  28 * (01/22/2001) gb
  29 *      Added write_room() and chars_in_buffer() support.
  30 *
  31 * (12/21/2000) gb
  32 *      Moved termio stuff inside the port->active check.
  33 *      Moved MOD_DEC_USE_COUNT to end of empeg_close().
  34 *
  35 * (12/03/2000) gb
  36 *      Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open().
  37 *      This notifies the tty driver that the termios have changed.
  38 *
  39 * (11/13/2000) gb
  40 *      Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
  41 *      empeg_open() (It only needs to be set once - Doh!)
  42 *
  43 * (11/11/2000) gb
  44 *      Updated to work with id_table structure.
  45 *
  46 * (11/04/2000) gb
  47 *      Forked this from visor.c, and hacked it up to work with an
  48 *      Empeg ltd. empeg-car player.  Constructive criticism welcomed.
  49 *      I would like to say, 'Thank You' to Greg Kroah-Hartman for the
  50 *      use of his code, and for his guidance, advice and patience. :)
  51 *      A 'Thank You' is in order for John Ripley of Empeg ltd for his
  52 *      advice, and patience too.
  53 *
  54 */
  55
  56#include <linux/kernel.h>
  57#include <linux/errno.h>
  58#include <linux/init.h>
  59#include <linux/slab.h>
  60#include <linux/tty.h>
  61#include <linux/tty_driver.h>
  62#include <linux/tty_flip.h>
  63#include <linux/module.h>
  64#include <linux/spinlock.h>
  65#include <linux/uaccess.h>
  66#include <linux/usb.h>
  67#include <linux/usb/serial.h>
  68
  69static int debug;
  70
  71/*
  72 * Version Information
  73 */
  74#define DRIVER_VERSION "v1.2"
  75#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
  76#define DRIVER_DESC "USB Empeg Mark I/II Driver"
  77
  78#define EMPEG_VENDOR_ID                 0x084f
  79#define EMPEG_PRODUCT_ID                0x0001
  80
  81/* function prototypes for an empeg-car player */
  82static int  empeg_open(struct tty_struct *tty, struct usb_serial_port *port);
  83static void empeg_close(struct usb_serial_port *port);
  84static int  empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
  85                                                const unsigned char *buf,
  86                                                int count);
  87static int  empeg_write_room(struct tty_struct *tty);
  88static int  empeg_chars_in_buffer(struct tty_struct *tty);
  89static void empeg_throttle(struct tty_struct *tty);
  90static void empeg_unthrottle(struct tty_struct *tty);
  91static int  empeg_startup(struct usb_serial *serial);
  92static void empeg_init_termios(struct tty_struct *tty);
  93static void empeg_write_bulk_callback(struct urb *urb);
  94static void empeg_read_bulk_callback(struct urb *urb);
  95
  96static struct usb_device_id id_table [] = {
  97        { USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
  98        { }                                     /* Terminating entry */
  99};
 100
 101MODULE_DEVICE_TABLE(usb, id_table);
 102
 103static struct usb_driver empeg_driver = {
 104        .name =         "empeg",
 105        .probe =        usb_serial_probe,
 106        .disconnect =   usb_serial_disconnect,
 107        .id_table =     id_table,
 108        .no_dynamic_id =        1,
 109};
 110
 111static struct usb_serial_driver empeg_device = {
 112        .driver = {
 113                .owner =        THIS_MODULE,
 114                .name =         "empeg",
 115        },
 116        .id_table =             id_table,
 117        .usb_driver =           &empeg_driver,
 118        .num_ports =            1,
 119        .open =                 empeg_open,
 120        .close =                empeg_close,
 121        .throttle =             empeg_throttle,
 122        .unthrottle =           empeg_unthrottle,
 123        .attach =               empeg_startup,
 124        .init_termios =         empeg_init_termios,
 125        .write =                empeg_write,
 126        .write_room =           empeg_write_room,
 127        .chars_in_buffer =      empeg_chars_in_buffer,
 128        .write_bulk_callback =  empeg_write_bulk_callback,
 129        .read_bulk_callback =   empeg_read_bulk_callback,
 130};
 131
 132#define NUM_URBS                        16
 133#define URB_TRANSFER_BUFFER_SIZE        4096
 134
 135static struct urb       *write_urb_pool[NUM_URBS];
 136static spinlock_t       write_urb_pool_lock;
 137static int              bytes_in;
 138static int              bytes_out;
 139
 140/******************************************************************************
 141 * Empeg specific driver functions
 142 ******************************************************************************/
 143static int empeg_open(struct tty_struct *tty,struct usb_serial_port *port)
 144{
 145        struct usb_serial *serial = port->serial;
 146        int result = 0;
 147
 148        dbg("%s - port %d", __func__, port->number);
 149
 150        bytes_in = 0;
 151        bytes_out = 0;
 152
 153        /* Start reading from the device */
 154        usb_fill_bulk_urb(
 155                port->read_urb,
 156                serial->dev,
 157                usb_rcvbulkpipe(serial->dev,
 158                        port->bulk_in_endpointAddress),
 159                port->read_urb->transfer_buffer,
 160                port->read_urb->transfer_buffer_length,
 161                empeg_read_bulk_callback,
 162                port);
 163
 164        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 165
 166        if (result)
 167                dev_err(&port->dev,
 168                        "%s - failed submitting read urb, error %d\n",
 169                                                        __func__, result);
 170
 171        return result;
 172}
 173
 174
 175static void empeg_close(struct usb_serial_port *port)
 176{
 177        dbg("%s - port %d", __func__, port->number);
 178
 179        /* shutdown our bulk read */
 180        usb_kill_urb(port->read_urb);
 181        /* Uncomment the following line if you want to see some statistics in your syslog */
 182        /* dev_info (&port->dev, "Bytes In = %d  Bytes Out = %d\n", bytes_in, bytes_out); */
 183}
 184
 185
 186static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
 187                                        const unsigned char *buf, int count)
 188{
 189        struct usb_serial *serial = port->serial;
 190        struct urb *urb;
 191        const unsigned char *current_position = buf;
 192        unsigned long flags;
 193        int status;
 194        int i;
 195        int bytes_sent = 0;
 196        int transfer_size;
 197
 198        dbg("%s - port %d", __func__, port->number);
 199
 200        while (count > 0) {
 201                /* try to find a free urb in our list of them */
 202                urb = NULL;
 203
 204                spin_lock_irqsave(&write_urb_pool_lock, flags);
 205
 206                for (i = 0; i < NUM_URBS; ++i) {
 207                        if (write_urb_pool[i]->status != -EINPROGRESS) {
 208                                urb = write_urb_pool[i];
 209                                break;
 210                        }
 211                }
 212
 213                spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 214
 215                if (urb == NULL) {
 216                        dbg("%s - no more free urbs", __func__);
 217                        goto exit;
 218                }
 219
 220                if (urb->transfer_buffer == NULL) {
 221                        urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
 222                        if (urb->transfer_buffer == NULL) {
 223                                dev_err(&port->dev,
 224                                        "%s no more kernel memory...\n",
 225                                                                __func__);
 226                                goto exit;
 227                        }
 228                }
 229
 230                transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
 231
 232                memcpy(urb->transfer_buffer, current_position, transfer_size);
 233
 234                usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
 235
 236                /* build up our urb */
 237                usb_fill_bulk_urb(
 238                        urb,
 239                        serial->dev,
 240                        usb_sndbulkpipe(serial->dev,
 241                                        port->bulk_out_endpointAddress),
 242                        urb->transfer_buffer,
 243                        transfer_size,
 244                        empeg_write_bulk_callback,
 245                        port);
 246
 247                /* send it down the pipe */
 248                status = usb_submit_urb(urb, GFP_ATOMIC);
 249                if (status) {
 250                        dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status);
 251                        bytes_sent = status;
 252                        break;
 253                }
 254
 255                current_position += transfer_size;
 256                bytes_sent += transfer_size;
 257                count -= transfer_size;
 258                bytes_out += transfer_size;
 259
 260        }
 261exit:
 262        return bytes_sent;
 263}
 264
 265
 266static int empeg_write_room(struct tty_struct *tty)
 267{
 268        struct usb_serial_port *port = tty->driver_data;
 269        unsigned long flags;
 270        int i;
 271        int room = 0;
 272
 273        dbg("%s - port %d", __func__, port->number);
 274
 275        spin_lock_irqsave(&write_urb_pool_lock, flags);
 276        /* tally up the number of bytes available */
 277        for (i = 0; i < NUM_URBS; ++i) {
 278                if (write_urb_pool[i]->status != -EINPROGRESS)
 279                        room += URB_TRANSFER_BUFFER_SIZE;
 280        }
 281        spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 282        dbg("%s - returns %d", __func__, room);
 283        return room;
 284
 285}
 286
 287
 288static int empeg_chars_in_buffer(struct tty_struct *tty)
 289{
 290        struct usb_serial_port *port = tty->driver_data;
 291        unsigned long flags;
 292        int i;
 293        int chars = 0;
 294
 295        dbg("%s - port %d", __func__, port->number);
 296
 297        spin_lock_irqsave(&write_urb_pool_lock, flags);
 298
 299        /* tally up the number of bytes waiting */
 300        for (i = 0; i < NUM_URBS; ++i) {
 301                if (write_urb_pool[i]->status == -EINPROGRESS)
 302                        chars += URB_TRANSFER_BUFFER_SIZE;
 303        }
 304
 305        spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 306        dbg("%s - returns %d", __func__, chars);
 307        return chars;
 308}
 309
 310
 311static void empeg_write_bulk_callback(struct urb *urb)
 312{
 313        struct usb_serial_port *port = urb->context;
 314        int status = urb->status;
 315
 316        dbg("%s - port %d", __func__, port->number);
 317
 318        if (status) {
 319                dbg("%s - nonzero write bulk status received: %d",
 320                    __func__, status);
 321                return;
 322        }
 323
 324        usb_serial_port_softint(port);
 325}
 326
 327
 328static void empeg_read_bulk_callback(struct urb *urb)
 329{
 330        struct usb_serial_port *port = urb->context;
 331        struct tty_struct *tty;
 332        unsigned char *data = urb->transfer_buffer;
 333        int result;
 334        int status = urb->status;
 335
 336        dbg("%s - port %d", __func__, port->number);
 337
 338        if (status) {
 339                dbg("%s - nonzero read bulk status received: %d",
 340                    __func__, status);
 341                return;
 342        }
 343
 344        usb_serial_debug_data(debug, &port->dev, __func__,
 345                                                urb->actual_length, data);
 346        tty = tty_port_tty_get(&port->port);
 347
 348        if (urb->actual_length) {
 349                tty_buffer_request_room(tty, urb->actual_length);
 350                tty_insert_flip_string(tty, data, urb->actual_length);
 351                tty_flip_buffer_push(tty);
 352                bytes_in += urb->actual_length;
 353        }
 354        tty_kref_put(tty);
 355
 356        /* Continue trying to always read  */
 357        usb_fill_bulk_urb(
 358                port->read_urb,
 359                port->serial->dev,
 360                usb_rcvbulkpipe(port->serial->dev,
 361                        port->bulk_in_endpointAddress),
 362                port->read_urb->transfer_buffer,
 363                port->read_urb->transfer_buffer_length,
 364                empeg_read_bulk_callback,
 365                port);
 366
 367        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 368
 369        if (result)
 370                dev_err(&urb->dev->dev,
 371                        "%s - failed resubmitting read urb, error %d\n",
 372                                                        __func__, result);
 373
 374        return;
 375
 376}
 377
 378
 379static void empeg_throttle(struct tty_struct *tty)
 380{
 381        struct usb_serial_port *port = tty->driver_data;
 382        dbg("%s - port %d", __func__, port->number);
 383        usb_kill_urb(port->read_urb);
 384}
 385
 386
 387static void empeg_unthrottle(struct tty_struct *tty)
 388{
 389        struct usb_serial_port *port = tty->driver_data;
 390        int result;
 391        dbg("%s - port %d", __func__, port->number);
 392
 393        port->read_urb->dev = port->serial->dev;
 394        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 395        if (result)
 396                dev_err(&port->dev,
 397                        "%s - failed submitting read urb, error %d\n",
 398                                                        __func__, result);
 399}
 400
 401
 402static int  empeg_startup(struct usb_serial *serial)
 403{
 404        int r;
 405
 406        dbg("%s", __func__);
 407
 408        if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
 409                dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
 410                        serial->dev->actconfig->desc.bConfigurationValue);
 411                return -ENODEV;
 412        }
 413        dbg("%s - reset config", __func__);
 414        r = usb_reset_configuration(serial->dev);
 415
 416        /* continue on with initialization */
 417        return r;
 418
 419}
 420
 421
 422static void empeg_init_termios(struct tty_struct *tty)
 423{
 424        struct ktermios *termios = tty->termios;
 425
 426        /*
 427         * The empeg-car player wants these particular tty settings.
 428         * You could, for example, change the baud rate, however the
 429         * player only supports 115200 (currently), so there is really
 430         * no point in support for changes to the tty settings.
 431         * (at least for now)
 432         *
 433         * The default requirements for this device are:
 434         */
 435        termios->c_iflag
 436                &= ~(IGNBRK     /* disable ignore break */
 437                | BRKINT        /* disable break causes interrupt */
 438                | PARMRK        /* disable mark parity errors */
 439                | ISTRIP        /* disable clear high bit of input characters */
 440                | INLCR         /* disable translate NL to CR */
 441                | IGNCR         /* disable ignore CR */
 442                | ICRNL         /* disable translate CR to NL */
 443                | IXON);        /* disable enable XON/XOFF flow control */
 444
 445        termios->c_oflag
 446                &= ~OPOST;      /* disable postprocess output characters */
 447
 448        termios->c_lflag
 449                &= ~(ECHO       /* disable echo input characters */
 450                | ECHONL        /* disable echo new line */
 451                | ICANON        /* disable erase, kill, werase, and rprnt special characters */
 452                | ISIG          /* disable interrupt, quit, and suspend special characters */
 453                | IEXTEN);      /* disable non-POSIX special characters */
 454
 455        termios->c_cflag
 456                &= ~(CSIZE      /* no size */
 457                | PARENB        /* disable parity bit */
 458                | CBAUD);       /* clear current baud rate */
 459
 460        termios->c_cflag
 461                |= CS8;         /* character size 8 bits */
 462
 463        tty_encode_baud_rate(tty, 115200, 115200);
 464}
 465
 466
 467static int __init empeg_init(void)
 468{
 469        struct urb *urb;
 470        int i, retval;
 471
 472        /* create our write urb pool and transfer buffers */
 473        spin_lock_init(&write_urb_pool_lock);
 474        for (i = 0; i < NUM_URBS; ++i) {
 475                urb = usb_alloc_urb(0, GFP_KERNEL);
 476                write_urb_pool[i] = urb;
 477                if (urb == NULL) {
 478                        printk(KERN_ERR "empeg: No more urbs???\n");
 479                        continue;
 480                }
 481
 482                urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
 483                                                                GFP_KERNEL);
 484                if (!urb->transfer_buffer) {
 485                        printk(KERN_ERR "empeg: %s - out of memory for urb "
 486                               "buffers.", __func__);
 487                        continue;
 488                }
 489        }
 490
 491        retval = usb_serial_register(&empeg_device);
 492        if (retval)
 493                goto failed_usb_serial_register;
 494        retval = usb_register(&empeg_driver);
 495        if (retval)
 496                goto failed_usb_register;
 497
 498        printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
 499               DRIVER_DESC "\n");
 500
 501        return 0;
 502failed_usb_register:
 503        usb_serial_deregister(&empeg_device);
 504failed_usb_serial_register:
 505        for (i = 0; i < NUM_URBS; ++i) {
 506                if (write_urb_pool[i]) {
 507                        kfree(write_urb_pool[i]->transfer_buffer);
 508                        usb_free_urb(write_urb_pool[i]);
 509                }
 510        }
 511        return retval;
 512}
 513
 514
 515static void __exit empeg_exit(void)
 516{
 517        int i;
 518        unsigned long flags;
 519
 520        usb_deregister(&empeg_driver);
 521        usb_serial_deregister(&empeg_device);
 522
 523        spin_lock_irqsave(&write_urb_pool_lock, flags);
 524
 525        for (i = 0; i < NUM_URBS; ++i) {
 526                if (write_urb_pool[i]) {
 527                        /* FIXME - uncomment the following usb_kill_urb call
 528                         * when the host controllers get fixed to set urb->dev
 529                         * = NULL after the urb is finished.  Otherwise this
 530                         * call oopses. */
 531                        /* usb_kill_urb(write_urb_pool[i]); */
 532                        kfree(write_urb_pool[i]->transfer_buffer);
 533                        usb_free_urb(write_urb_pool[i]);
 534                }
 535        }
 536        spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 537}
 538
 539
 540module_init(empeg_init);
 541module_exit(empeg_exit);
 542
 543MODULE_AUTHOR(DRIVER_AUTHOR);
 544MODULE_DESCRIPTION(DRIVER_DESC);
 545MODULE_LICENSE("GPL");
 546
 547module_param(debug, bool, S_IRUGO | S_IWUSR);
 548MODULE_PARM_DESC(debug, "Debug enabled or not");
 549