patch-2.2.19 linux/drivers/usb/serial/usbserial.c
Next file: linux/drivers/usb/serial/visor.c
Previous file: linux/drivers/usb/serial/usb-serial.h
Back to the patch index
Back to the overall index
- Lines: 261
- Date:
Sun Mar 25 11:37:37 2001
- Orig file:
v2.2.18/drivers/usb/serial/usbserial.c
- Orig date:
Sun Mar 25 11:28:32 2001
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
@@ -14,6 +14,23 @@
* based on a driver by Brad Keryan)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * 2001_02_05 gkh
+ * Fixed buffer overflows bug with the generic serial driver. Thanks to
+ * Todd Squires <squirest@ct0.com> for fixing this.
+ *
+ * (12/12/2000) gkh
+ * Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+ * moved them to the serial_open and serial_close functions.
+ * Also fixed bug with there not being a MOD_DEC for the generic driver
+ * (thanks to Gary Brubaker for finding this.)
+ *
+ * (12/29/2000) gkh
+ * Small NULL pointer initialization cleanup which saves a bit of disk image
+ *
+ * (10/05/2000) gkh
+ * Fixed bug with urb->dev not being set properly, now that the usb
+ * core needs it.
*
* (09/11/2000) gkh
* Removed DEBUG #ifdefs with call to usb_serial_debug_data
@@ -239,9 +256,9 @@
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/fcntl.h>
+#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
-#include <linux/tty.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/list.h>
@@ -327,7 +344,7 @@
static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
static struct termios * serial_termios[SERIAL_TTY_MINORS];
static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, };
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
LIST_HEAD(usb_serial_driver_list);
@@ -449,6 +466,8 @@
return -ENODEV;
}
+ MOD_INC_USE_COUNT;
+
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor;
port = &serial->port[portNumber];
@@ -486,6 +505,8 @@
} else {
generic_close(port, filp);
}
+
+ MOD_DEC_USE_COUNT;
}
@@ -694,25 +715,40 @@
{
struct usb_serial *serial = port->serial;
unsigned long flags;
+ int result;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
+ MOD_INC_USE_COUNT;
+
dbg(__FUNCTION__ " - port %d", port->number);
spin_lock_irqsave (&port->port_lock, flags);
++port->open_count;
- MOD_INC_USE_COUNT;
if (!port->active) {
port->active = 1;
+ /* force low_latency on so that our tty_push actually forces the data through,
+ otherwise it is scheduled, and with high data rates (like with OHCI) data
+ can get lost. */
+ port->tty->low_latency = 1;
+
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
- /*Start reading from the device*/
- if (usb_submit_urb(port->read_urb))
- dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
+ /* Start reading from the device */
+ 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,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback),
+ port);
+ result = usb_submit_urb(port->read_urb);
+ if (result)
+ err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
}
@@ -745,6 +781,7 @@
}
spin_unlock_irqrestore (&port->port_lock, flags);
+ MOD_DEC_USE_COUNT;
}
@@ -752,6 +789,7 @@
{
struct usb_serial *serial = port->serial;
unsigned long flags;
+ int result;
dbg(__FUNCTION__ " - port %d", port->number);
@@ -779,11 +817,19 @@
memcpy (port->write_urb->transfer_buffer, buf, count);
}
- /* send the data out the bulk port */
- port->write_urb->transfer_buffer_length = count;
+ /* set up our urb */
+ FILL_BULK_URB(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ generic_write_bulk_callback),
+ port);
- if (usb_submit_urb(port->write_urb)) {
- dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed");
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb);
+ if (result) {
+ err(__FUNCTION__ " - failed submitting write urb, error %d", result);
spin_unlock_irqrestore (&port->port_lock, flags);
return 0;
}
@@ -836,6 +882,7 @@
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
+ int result;
dbg(__FUNCTION__ " - port %d", port->number);
@@ -854,16 +901,27 @@
tty = port->tty;
if (urb->actual_length) {
for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* this doesn't actually push the data through unless tty->low_latency is set */
+ tty_insert_flip_char(tty, data[i], 0);
+ }
tty_flip_buffer_push(tty);
}
/* Continue trying to always read */
- if (usb_submit_urb(urb))
- dbg(__FUNCTION__ " - failed resubmitting read urb");
-
- return;
+ 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,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback),
+ port);
+ result = usb_submit_urb(port->read_urb);
+ if (result)
+ err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
@@ -1024,7 +1082,6 @@
}
/* found all that we need */
- MOD_INC_USE_COUNT;
info("%s converter detected", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC
@@ -1032,7 +1089,6 @@
num_ports = num_bulk_out;
if (num_ports == 0) {
err("Generic device with no bulk out, not allowed.");
- MOD_DEC_USE_COUNT;
return NULL;
}
} else
@@ -1042,7 +1098,6 @@
serial = get_free_serial (num_ports, &minor);
if (serial == NULL) {
err("No more free serial devices");
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1072,6 +1127,7 @@
goto probe_error;
}
buffer_size = endpoint->wMaxPacketSize;
+ port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->bulk_in_buffer) {
err("Couldn't allocate bulk_in_buffer");
@@ -1120,6 +1176,7 @@
goto probe_error;
}
buffer_size = endpoint->wMaxPacketSize;
+ port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->interrupt_in_buffer) {
err("Couldn't allocate interrupt_in_buffer");
@@ -1137,6 +1194,7 @@
/* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
max_endpoints = MAX(num_bulk_in, num_bulk_out);
max_endpoints = MAX(max_endpoints, num_interrupt_in);
+ dbg (__FUNCTION__ " - setting up %d port structures for this device", max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = &serial->port[i];
port->number = i + serial->minor;
@@ -1185,7 +1243,6 @@
/* free up any memory that we allocated */
kfree (serial);
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1252,14 +1309,13 @@
info("device disconnected");
}
- MOD_DEC_USE_COUNT;
}
static struct tty_driver serial_tty_driver = {
magic: TTY_DRIVER_MAGIC,
driver_name: "usb-serial",
- name: "usb/tts/%d",
+ name: "ttyUSB",
major: SERIAL_TTY_MAJOR,
minor_start: 0,
num: SERIAL_TTY_MINORS,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)