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