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

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)