linux/drivers/usb/serial/opticon.c
<<
>>
Prefs
   1/*
   2 * Opticon USB barcode to serial driver
   3 *
   4 * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com>
   5 * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>
   6 * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
   7 * Copyright (C) 2008 - 2009 Novell Inc.
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License version
  11 *      2 as published by the Free Software Foundation.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/tty.h>
  16#include <linux/tty_driver.h>
  17#include <linux/slab.h>
  18#include <linux/tty_flip.h>
  19#include <linux/serial.h>
  20#include <linux/module.h>
  21#include <linux/usb.h>
  22#include <linux/usb/serial.h>
  23#include <linux/uaccess.h>
  24
  25#define CONTROL_RTS                     0x02
  26#define RESEND_CTS_STATE        0x03
  27
  28/* max number of write urbs in flight */
  29#define URB_UPPER_LIMIT 8
  30
  31/* This driver works for the Opticon 1D barcode reader
  32 * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */
  33#define DRIVER_DESC     "Opticon USB barcode to serial driver (1D)"
  34
  35static const struct usb_device_id id_table[] = {
  36        { USB_DEVICE(0x065a, 0x0009) },
  37        { },
  38};
  39MODULE_DEVICE_TABLE(usb, id_table);
  40
  41/* This structure holds all of the individual device information */
  42struct opticon_private {
  43        spinlock_t lock;        /* protects the following flags */
  44        bool rts;
  45        bool cts;
  46        int outstanding_urbs;
  47};
  48
  49
  50static void opticon_process_data_packet(struct usb_serial_port *port,
  51                                        const unsigned char *buf, size_t len)
  52{
  53        tty_insert_flip_string(&port->port, buf, len);
  54        tty_flip_buffer_push(&port->port);
  55}
  56
  57static void opticon_process_status_packet(struct usb_serial_port *port,
  58                                        const unsigned char *buf, size_t len)
  59{
  60        struct opticon_private *priv = usb_get_serial_port_data(port);
  61        unsigned long flags;
  62
  63        spin_lock_irqsave(&priv->lock, flags);
  64        if (buf[0] == 0x00)
  65                priv->cts = false;
  66        else
  67                priv->cts = true;
  68        spin_unlock_irqrestore(&priv->lock, flags);
  69}
  70
  71static void opticon_process_read_urb(struct urb *urb)
  72{
  73        struct usb_serial_port *port = urb->context;
  74        const unsigned char *hdr = urb->transfer_buffer;
  75        const unsigned char *data = hdr + 2;
  76        size_t data_len = urb->actual_length - 2;
  77
  78        if (urb->actual_length <= 2) {
  79                dev_dbg(&port->dev, "malformed packet received: %d bytes\n",
  80                                                        urb->actual_length);
  81                return;
  82        }
  83        /*
  84         * Data from the device comes with a 2 byte header:
  85         *
  86         * <0x00><0x00>data...
  87         *      This is real data to be sent to the tty layer
  88         * <0x00><0x01>level
  89         *      This is a CTS level change, the third byte is the CTS
  90         *      value (0 for low, 1 for high).
  91         */
  92        if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) {
  93                opticon_process_data_packet(port, data, data_len);
  94        } else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) {
  95                opticon_process_status_packet(port, data, data_len);
  96        } else {
  97                dev_dbg(&port->dev, "unknown packet received: %02x %02x\n",
  98                                                        hdr[0], hdr[1]);
  99        }
 100}
 101
 102static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 103                                u8 val)
 104{
 105        struct usb_serial *serial = port->serial;
 106        int retval;
 107        u8 *buffer;
 108
 109        buffer = kzalloc(1, GFP_KERNEL);
 110        if (!buffer)
 111                return -ENOMEM;
 112
 113        buffer[0] = val;
 114        /* Send the message to the vendor control endpoint
 115         * of the connected device */
 116        retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 117                                requesttype,
 118                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
 119                                0, 0, buffer, 1, 0);
 120        kfree(buffer);
 121
 122        if (retval < 0)
 123                return retval;
 124
 125        return 0;
 126}
 127
 128static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
 129{
 130        struct opticon_private *priv = usb_get_serial_port_data(port);
 131        unsigned long flags;
 132        int res;
 133
 134        spin_lock_irqsave(&priv->lock, flags);
 135        priv->rts = false;
 136        spin_unlock_irqrestore(&priv->lock, flags);
 137
 138        /* Clear RTS line */
 139        send_control_msg(port, CONTROL_RTS, 0);
 140
 141        /* clear the halt status of the endpoint */
 142        usb_clear_halt(port->serial->dev, port->read_urb->pipe);
 143
 144        res = usb_serial_generic_open(tty, port);
 145        if (res)
 146                return res;
 147
 148        /* Request CTS line state, sometimes during opening the current
 149         * CTS state can be missed. */
 150        send_control_msg(port, RESEND_CTS_STATE, 1);
 151
 152        return res;
 153}
 154
 155static void opticon_write_control_callback(struct urb *urb)
 156{
 157        struct usb_serial_port *port = urb->context;
 158        struct opticon_private *priv = usb_get_serial_port_data(port);
 159        int status = urb->status;
 160        unsigned long flags;
 161
 162        /* free up the transfer buffer, as usb_free_urb() does not do this */
 163        kfree(urb->transfer_buffer);
 164
 165        /* setup packet may be set if we're using it for writing */
 166        kfree(urb->setup_packet);
 167
 168        if (status)
 169                dev_dbg(&port->dev,
 170                        "%s - non-zero urb status received: %d\n",
 171                        __func__, status);
 172
 173        spin_lock_irqsave(&priv->lock, flags);
 174        --priv->outstanding_urbs;
 175        spin_unlock_irqrestore(&priv->lock, flags);
 176
 177        usb_serial_port_softint(port);
 178}
 179
 180static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 181                         const unsigned char *buf, int count)
 182{
 183        struct opticon_private *priv = usb_get_serial_port_data(port);
 184        struct usb_serial *serial = port->serial;
 185        struct urb *urb;
 186        unsigned char *buffer;
 187        unsigned long flags;
 188        int status;
 189        struct usb_ctrlrequest *dr;
 190
 191        spin_lock_irqsave(&priv->lock, flags);
 192        if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
 193                spin_unlock_irqrestore(&priv->lock, flags);
 194                dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
 195                return 0;
 196        }
 197        priv->outstanding_urbs++;
 198        spin_unlock_irqrestore(&priv->lock, flags);
 199
 200        buffer = kmalloc(count, GFP_ATOMIC);
 201        if (!buffer) {
 202                count = -ENOMEM;
 203                goto error_no_buffer;
 204        }
 205
 206        urb = usb_alloc_urb(0, GFP_ATOMIC);
 207        if (!urb) {
 208                count = -ENOMEM;
 209                goto error_no_urb;
 210        }
 211
 212        memcpy(buffer, buf, count);
 213
 214        usb_serial_debug_data(&port->dev, __func__, count, buffer);
 215
 216        /* The connected devices do not have a bulk write endpoint,
 217         * to transmit data to de barcode device the control endpoint is used */
 218        dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
 219        if (!dr) {
 220                count = -ENOMEM;
 221                goto error_no_dr;
 222        }
 223
 224        dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
 225        dr->bRequest = 0x01;
 226        dr->wValue = 0;
 227        dr->wIndex = 0;
 228        dr->wLength = cpu_to_le16(count);
 229
 230        usb_fill_control_urb(urb, serial->dev,
 231                usb_sndctrlpipe(serial->dev, 0),
 232                (unsigned char *)dr, buffer, count,
 233                opticon_write_control_callback, port);
 234
 235        /* send it down the pipe */
 236        status = usb_submit_urb(urb, GFP_ATOMIC);
 237        if (status) {
 238                dev_err(&port->dev,
 239                "%s - usb_submit_urb(write endpoint) failed status = %d\n",
 240                                                        __func__, status);
 241                count = status;
 242                goto error;
 243        }
 244
 245        /* we are done with this urb, so let the host driver
 246         * really free it when it is finished with it */
 247        usb_free_urb(urb);
 248
 249        return count;
 250error:
 251        kfree(dr);
 252error_no_dr:
 253        usb_free_urb(urb);
 254error_no_urb:
 255        kfree(buffer);
 256error_no_buffer:
 257        spin_lock_irqsave(&priv->lock, flags);
 258        --priv->outstanding_urbs;
 259        spin_unlock_irqrestore(&priv->lock, flags);
 260        return count;
 261}
 262
 263static int opticon_write_room(struct tty_struct *tty)
 264{
 265        struct usb_serial_port *port = tty->driver_data;
 266        struct opticon_private *priv = usb_get_serial_port_data(port);
 267        unsigned long flags;
 268
 269        /*
 270         * We really can take almost anything the user throws at us
 271         * but let's pick a nice big number to tell the tty
 272         * layer that we have lots of free space, unless we don't.
 273         */
 274        spin_lock_irqsave(&priv->lock, flags);
 275        if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
 276                spin_unlock_irqrestore(&priv->lock, flags);
 277                dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
 278                return 0;
 279        }
 280        spin_unlock_irqrestore(&priv->lock, flags);
 281
 282        return 2048;
 283}
 284
 285static int opticon_tiocmget(struct tty_struct *tty)
 286{
 287        struct usb_serial_port *port = tty->driver_data;
 288        struct opticon_private *priv = usb_get_serial_port_data(port);
 289        unsigned long flags;
 290        int result = 0;
 291
 292        spin_lock_irqsave(&priv->lock, flags);
 293        if (priv->rts)
 294                result |= TIOCM_RTS;
 295        if (priv->cts)
 296                result |= TIOCM_CTS;
 297        spin_unlock_irqrestore(&priv->lock, flags);
 298
 299        dev_dbg(&port->dev, "%s - %x\n", __func__, result);
 300        return result;
 301}
 302
 303static int opticon_tiocmset(struct tty_struct *tty,
 304                           unsigned int set, unsigned int clear)
 305{
 306        struct usb_serial_port *port = tty->driver_data;
 307        struct opticon_private *priv = usb_get_serial_port_data(port);
 308        unsigned long flags;
 309        bool rts;
 310        bool changed = false;
 311        int ret;
 312
 313        /* We only support RTS so we only handle that */
 314        spin_lock_irqsave(&priv->lock, flags);
 315
 316        rts = priv->rts;
 317        if (set & TIOCM_RTS)
 318                priv->rts = true;
 319        if (clear & TIOCM_RTS)
 320                priv->rts = false;
 321        changed = rts ^ priv->rts;
 322        spin_unlock_irqrestore(&priv->lock, flags);
 323
 324        if (!changed)
 325                return 0;
 326
 327        ret = send_control_msg(port, CONTROL_RTS, !rts);
 328        if (ret)
 329                return usb_translate_errors(ret);
 330
 331        return 0;
 332}
 333
 334static int get_serial_info(struct usb_serial_port *port,
 335                           struct serial_struct __user *serial)
 336{
 337        struct serial_struct tmp;
 338
 339        memset(&tmp, 0x00, sizeof(tmp));
 340
 341        /* fake emulate a 16550 uart to make userspace code happy */
 342        tmp.type                = PORT_16550A;
 343        tmp.line                = port->minor;
 344        tmp.port                = 0;
 345        tmp.irq                 = 0;
 346        tmp.xmit_fifo_size      = 1024;
 347        tmp.baud_base           = 9600;
 348        tmp.close_delay         = 5*HZ;
 349        tmp.closing_wait        = 30*HZ;
 350
 351        if (copy_to_user(serial, &tmp, sizeof(*serial)))
 352                return -EFAULT;
 353        return 0;
 354}
 355
 356static int opticon_ioctl(struct tty_struct *tty,
 357                         unsigned int cmd, unsigned long arg)
 358{
 359        struct usb_serial_port *port = tty->driver_data;
 360
 361        switch (cmd) {
 362        case TIOCGSERIAL:
 363                return get_serial_info(port,
 364                                       (struct serial_struct __user *)arg);
 365        }
 366
 367        return -ENOIOCTLCMD;
 368}
 369
 370static int opticon_startup(struct usb_serial *serial)
 371{
 372        if (!serial->num_bulk_in) {
 373                dev_err(&serial->dev->dev, "no bulk in endpoint\n");
 374                return -ENODEV;
 375        }
 376
 377        return 0;
 378}
 379
 380static int opticon_port_probe(struct usb_serial_port *port)
 381{
 382        struct opticon_private *priv;
 383
 384        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 385        if (!priv)
 386                return -ENOMEM;
 387
 388        spin_lock_init(&priv->lock);
 389
 390        usb_set_serial_port_data(port, priv);
 391
 392        return 0;
 393}
 394
 395static int opticon_port_remove(struct usb_serial_port *port)
 396{
 397        struct opticon_private *priv = usb_get_serial_port_data(port);
 398
 399        kfree(priv);
 400
 401        return 0;
 402}
 403
 404static struct usb_serial_driver opticon_device = {
 405        .driver = {
 406                .owner =        THIS_MODULE,
 407                .name =         "opticon",
 408        },
 409        .id_table =             id_table,
 410        .num_ports =            1,
 411        .bulk_in_size =         256,
 412        .attach =               opticon_startup,
 413        .port_probe =           opticon_port_probe,
 414        .port_remove =          opticon_port_remove,
 415        .open =                 opticon_open,
 416        .write =                opticon_write,
 417        .write_room =           opticon_write_room,
 418        .throttle =             usb_serial_generic_throttle,
 419        .unthrottle =           usb_serial_generic_unthrottle,
 420        .ioctl =                opticon_ioctl,
 421        .tiocmget =             opticon_tiocmget,
 422        .tiocmset =             opticon_tiocmset,
 423        .process_read_urb =     opticon_process_read_urb,
 424};
 425
 426static struct usb_serial_driver * const serial_drivers[] = {
 427        &opticon_device, NULL
 428};
 429
 430module_usb_serial_driver(serial_drivers, id_table);
 431
 432MODULE_DESCRIPTION(DRIVER_DESC);
 433MODULE_LICENSE("GPL");
 434