Loading drivers/usb/serial/opticon.c +122 −2 Original line number Original line Diff line number Diff line /* /* * Opticon USB barcode to serial driver * Opticon USB barcode to serial driver * * * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (C) 2008 Novell Inc. * Copyright (C) 2008 - 2009 Novell Inc. * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * modify it under the terms of the GNU General Public License version Loading Loading @@ -40,8 +40,12 @@ struct opticon_private { bool throttled; bool throttled; bool actually_throttled; bool actually_throttled; bool rts; bool rts; int outstanding_urbs; }; }; /* max number of write urbs in flight */ #define URB_UPPER_LIMIT 4 static void opticon_bulk_callback(struct urb *urb) static void opticon_bulk_callback(struct urb *urb) { { struct opticon_private *priv = urb->context; struct opticon_private *priv = urb->context; Loading Loading @@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, usb_kill_urb(priv->bulk_read_urb); usb_kill_urb(priv->bulk_read_urb); } } static void opticon_write_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; int status = urb->status; unsigned long flags; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); if (status) dbg("%s - nonzero write bulk status received: %d", __func__, status); spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(priv->port); } static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct opticon_private *priv = usb_get_serial_data(port->serial); struct usb_serial *serial = port->serial; struct urb *urb; unsigned char *buffer; unsigned long flags; int status; dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - write limit hit\n", __func__); return 0; } priv->outstanding_urbs++; spin_unlock_irqrestore(&priv->lock, flags); buffer = kmalloc(count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; goto error_no_buffer; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { dev_err(&port->dev, "no more free urbs\n"); count = -ENOMEM; goto error_no_urb; } memcpy(buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), buffer, count, opticon_write_bulk_callback, priv); /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); count = status; goto error; } /* we are done with this urb, so let the host driver * really free it when it is finished with it */ usb_free_urb(urb); return count; error: usb_free_urb(urb); error_no_urb: kfree(buffer); error_no_buffer: spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); return count; } static int opticon_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_data(port->serial); unsigned long flags; dbg("%s - port %d", __func__, port->number); /* * We really can take almost anything the user throws at us * but let's pick a nice big number to tell the tty * layer that we have lots of free space, unless we don't. */ spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - write limit hit\n", __func__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); return 2048; } static void opticon_throttle(struct tty_struct *tty) static void opticon_throttle(struct tty_struct *tty) { { struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data; Loading Loading @@ -352,6 +470,8 @@ static struct usb_serial_driver opticon_device = { .attach = opticon_startup, .attach = opticon_startup, .open = opticon_open, .open = opticon_open, .close = opticon_close, .close = opticon_close, .write = opticon_write, .write_room = opticon_write_room, .shutdown = opticon_shutdown, .shutdown = opticon_shutdown, .throttle = opticon_throttle, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, .unthrottle = opticon_unthrottle, Loading Loading
drivers/usb/serial/opticon.c +122 −2 Original line number Original line Diff line number Diff line /* /* * Opticon USB barcode to serial driver * Opticon USB barcode to serial driver * * * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (C) 2008 Novell Inc. * Copyright (C) 2008 - 2009 Novell Inc. * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * modify it under the terms of the GNU General Public License version Loading Loading @@ -40,8 +40,12 @@ struct opticon_private { bool throttled; bool throttled; bool actually_throttled; bool actually_throttled; bool rts; bool rts; int outstanding_urbs; }; }; /* max number of write urbs in flight */ #define URB_UPPER_LIMIT 4 static void opticon_bulk_callback(struct urb *urb) static void opticon_bulk_callback(struct urb *urb) { { struct opticon_private *priv = urb->context; struct opticon_private *priv = urb->context; Loading Loading @@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, usb_kill_urb(priv->bulk_read_urb); usb_kill_urb(priv->bulk_read_urb); } } static void opticon_write_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; int status = urb->status; unsigned long flags; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); if (status) dbg("%s - nonzero write bulk status received: %d", __func__, status); spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(priv->port); } static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct opticon_private *priv = usb_get_serial_data(port->serial); struct usb_serial *serial = port->serial; struct urb *urb; unsigned char *buffer; unsigned long flags; int status; dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - write limit hit\n", __func__); return 0; } priv->outstanding_urbs++; spin_unlock_irqrestore(&priv->lock, flags); buffer = kmalloc(count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; goto error_no_buffer; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { dev_err(&port->dev, "no more free urbs\n"); count = -ENOMEM; goto error_no_urb; } memcpy(buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), buffer, count, opticon_write_bulk_callback, priv); /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); count = status; goto error; } /* we are done with this urb, so let the host driver * really free it when it is finished with it */ usb_free_urb(urb); return count; error: usb_free_urb(urb); error_no_urb: kfree(buffer); error_no_buffer: spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); return count; } static int opticon_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_data(port->serial); unsigned long flags; dbg("%s - port %d", __func__, port->number); /* * We really can take almost anything the user throws at us * but let's pick a nice big number to tell the tty * layer that we have lots of free space, unless we don't. */ spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - write limit hit\n", __func__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); return 2048; } static void opticon_throttle(struct tty_struct *tty) static void opticon_throttle(struct tty_struct *tty) { { struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data; Loading Loading @@ -352,6 +470,8 @@ static struct usb_serial_driver opticon_device = { .attach = opticon_startup, .attach = opticon_startup, .open = opticon_open, .open = opticon_open, .close = opticon_close, .close = opticon_close, .write = opticon_write, .write_room = opticon_write_room, .shutdown = opticon_shutdown, .shutdown = opticon_shutdown, .throttle = opticon_throttle, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, .unthrottle = opticon_unthrottle, Loading