diff options
Diffstat (limited to 'drivers/usb/serial/visor.c')
-rw-r--r-- | drivers/usb/serial/visor.c | 344 |
1 files changed, 16 insertions, 328 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 094942707c7..eb76aaef426 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -38,17 +38,9 @@ /* function prototypes for a handspring visor */ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port); static void visor_close(struct usb_serial_port *port); -static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count); -static int visor_write_room(struct tty_struct *tty); -static void visor_throttle(struct tty_struct *tty); -static void visor_unthrottle(struct tty_struct *tty); static int visor_probe(struct usb_serial *serial, const struct usb_device_id *id); static int visor_calc_num_ports(struct usb_serial *serial); -static void visor_release(struct usb_serial *serial); -static void visor_write_bulk_callback(struct urb *urb); -static void visor_read_bulk_callback(struct urb *urb); static void visor_read_int_callback(struct urb *urb); static int clie_3_5_startup(struct usb_serial *serial); static int treo_attach(struct usb_serial *serial); @@ -194,18 +186,14 @@ static struct usb_serial_driver handspring_device = { .usb_driver = &visor_driver, .id_table = id_table, .num_ports = 2, + .bulk_out_size = 256, .open = visor_open, .close = visor_close, - .throttle = visor_throttle, - .unthrottle = visor_unthrottle, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, .attach = treo_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, - .release = visor_release, - .write = visor_write, - .write_room = visor_write_room, - .write_bulk_callback = visor_write_bulk_callback, - .read_bulk_callback = visor_read_bulk_callback, .read_int_callback = visor_read_int_callback, }; @@ -219,18 +207,14 @@ static struct usb_serial_driver clie_5_device = { .usb_driver = &visor_driver, .id_table = clie_id_5_table, .num_ports = 2, + .bulk_out_size = 256, .open = visor_open, .close = visor_close, - .throttle = visor_throttle, - .unthrottle = visor_unthrottle, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, .attach = clie_5_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, - .release = visor_release, - .write = visor_write, - .write_room = visor_write_room, - .write_bulk_callback = visor_write_bulk_callback, - .read_bulk_callback = visor_read_bulk_callback, .read_int_callback = visor_read_int_callback, }; @@ -244,39 +228,19 @@ static struct usb_serial_driver clie_3_5_device = { .usb_driver = &visor_driver, .id_table = clie_id_3_5_table, .num_ports = 1, + .bulk_out_size = 256, .open = visor_open, .close = visor_close, - .throttle = visor_throttle, - .unthrottle = visor_unthrottle, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, .attach = clie_3_5_startup, - .write = visor_write, - .write_room = visor_write_room, - .write_bulk_callback = visor_write_bulk_callback, - .read_bulk_callback = visor_read_bulk_callback, }; -struct visor_private { - spinlock_t lock; - int bytes_in; - int bytes_out; - int outstanding_urbs; - unsigned char throttled; - unsigned char actually_throttled; -}; - -/* number of outstanding urbs to prevent userspace DoS from happening */ -#define URB_UPPER_LIMIT 42 - -static int stats; - /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; - struct visor_private *priv = usb_get_serial_port_data(port); - unsigned long flags; int result = 0; dbg("%s - port %d", __func__, port->number); @@ -287,26 +251,10 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) return -ENODEV; } - spin_lock_irqsave(&priv->lock, flags); - priv->bytes_in = 0; - priv->bytes_out = 0; - priv->throttled = 0; - spin_unlock_irqrestore(&priv->lock, flags); - /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - visor_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) { - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __func__, result); + result = usb_serial_generic_open(tty, port); + if (result) goto exit; - } if (port->interrupt_in_urb) { dbg("%s - adding interrupt input for treo", __func__); @@ -323,13 +271,12 @@ exit: static void visor_close(struct usb_serial_port *port) { - struct visor_private *priv = usb_get_serial_port_data(port); unsigned char *transfer_buffer; dbg("%s - port %d", __func__, port->number); /* shutdown our urbs */ - usb_kill_urb(port->read_urb); + usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); mutex_lock(&port->serial->disc_mutex); @@ -346,192 +293,6 @@ static void visor_close(struct usb_serial_port *port) } } mutex_unlock(&port->serial->disc_mutex); - - if (stats) - dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", - priv->bytes_in, priv->bytes_out); -} - - -static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count) -{ - struct visor_private *priv = usb_get_serial_port_data(port); - 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", __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, - visor_write_bulk_callback, port); - - /* 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; - } else { - spin_lock_irqsave(&priv->lock, flags); - priv->bytes_out += count; - spin_unlock_irqrestore(&priv->lock, flags); - } - - /* 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 visor_write_room(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct visor_private *priv = usb_get_serial_port_data(port); - unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - - /* - * We really can take 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", __func__); - return 0; - } - spin_unlock_irqrestore(&priv->lock, flags); - - return 2048; -} - - -static void visor_write_bulk_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct visor_private *priv = usb_get_serial_port_data(port); - int status = urb->status; - unsigned long flags; - - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree(urb->transfer_buffer); - - dbg("%s - port %d", __func__, port->number); - - 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(port); -} - - -static void visor_read_bulk_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct visor_private *priv = usb_get_serial_port_data(port); - unsigned char *data = urb->transfer_buffer; - int status = urb->status; - struct tty_struct *tty; - int result; - int available_room = 0; - - dbg("%s - port %d", __func__, port->number); - - if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); - return; - } - - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); - - if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, data, - urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } - spin_lock(&priv->lock); - if (tty) - priv->bytes_in += available_room; - - } else { - spin_lock(&priv->lock); - } - - /* Continue trying to always read if we should */ - if (!priv->throttled) { - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - visor_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, - "%s - failed resubmitting read urb, error %d\n", - __func__, result); - } else - priv->actually_throttled = 1; - spin_unlock(&priv->lock); } static void visor_read_int_callback(struct urb *urb) @@ -575,41 +336,6 @@ exit: __func__, result); } -static void visor_throttle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct visor_private *priv = usb_get_serial_port_data(port); - - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); - priv->throttled = 1; - spin_unlock_irq(&priv->lock); -} - - -static void visor_unthrottle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct visor_private *priv = usb_get_serial_port_data(port); - int result, was_throttled; - - dbg("%s - port %d", __func__, port->number); - spin_lock_irq(&priv->lock); - priv->throttled = 0; - was_throttled = priv->actually_throttled; - priv->actually_throttled = 0; - spin_unlock_irq(&priv->lock); - - if (was_throttled) { - port->read_urb->dev = port->serial->dev; - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __func__, result); - } -} - static int palm_os_3_probe(struct usb_serial *serial, const struct usb_device_id *id) { @@ -777,28 +503,6 @@ static int visor_calc_num_ports(struct usb_serial *serial) return num_ports; } -static int generic_startup(struct usb_serial *serial) -{ - struct usb_serial_port **ports = serial->port; - struct visor_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - while (i-- != 0) { - priv = usb_get_serial_port_data(ports[i]); - usb_set_serial_port_data(ports[i], NULL); - kfree(priv); - } - return -ENOMEM; - } - spin_lock_init(&priv->lock); - usb_set_serial_port_data(ports[i], priv); - } - return 0; -} - static int clie_3_5_startup(struct usb_serial *serial) { struct device *dev = &serial->dev->dev; @@ -849,7 +553,7 @@ static int clie_3_5_startup(struct usb_serial *serial) goto out; } - result = generic_startup(serial); + result = 0; out: kfree(data); @@ -867,7 +571,7 @@ static int treo_attach(struct usb_serial *serial) (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) || (serial->num_interrupt_in == 0)) - goto generic_startup; + return 0; dbg("%s", __func__); @@ -897,8 +601,7 @@ static int treo_attach(struct usb_serial *serial) COPY_PORT(serial->port[1], swap_port); kfree(swap_port); -generic_startup: - return generic_startup(serial); + return 0; } static int clie_5_attach(struct usb_serial *serial) @@ -921,20 +624,7 @@ static int clie_5_attach(struct usb_serial *serial) serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; - return generic_startup(serial); -} - -static void visor_release(struct usb_serial *serial) -{ - struct visor_private *priv; - int i; - - dbg("%s", __func__); - - for (i = 0; i < serial->num_ports; i++) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } + return 0; } static int __init visor_init(void) @@ -1018,8 +708,6 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); -module_param(stats, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(stats, "Enables statistics or not"); module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified vendor ID"); |