patch-2.4.6 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 --recursive --new-file v2.4.5/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- * Copyright (C) 1999, 2000 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 1999 - 2001 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (c) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com)
  *
@@ -15,6 +15,13 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (06/06/2001) gkh
+ *	added evil hack that is needed for the prolific pl2303 device due to the
+ *	crazy way its endpoints are set up.
+ *
+ * (05/30/2001) gkh
+ *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
  * (04/08/2001) gb
  *	Identify version on module load.
  *
@@ -284,13 +291,14 @@
 #endif
 
 #include "usb-serial.h"
+#include "pl2303.h"
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_VERSION "v1.2"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
-#define DRIVER_DESC "USB Serial Driver"
+#define DRIVER_DESC "USB Serial Driver core"
 
 #define MAX(a,b)	(((a)>(b))?(a):(b))
 
@@ -735,8 +743,7 @@
 static int generic_open (struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
-	unsigned long flags;
-	int result;
+	int result = 0;
 
 	if (port_paranoia_check (port, __FUNCTION__))
 		return -ENODEV;
@@ -745,7 +752,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	spin_lock_irqsave (&port->port_lock, flags);
+	down (&port->sem);
 	
 	++port->open_count;
 	
@@ -773,20 +780,19 @@
 		}
 	}
 	
-	spin_unlock_irqrestore (&port->port_lock, flags);
+	up (&port->sem);
 	
-	return 0;
+	return result;
 }
 
 
 static void generic_close (struct usb_serial_port *port, struct file * filp)
 {
 	struct usb_serial *serial = port->serial;
-	unsigned long flags;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	spin_lock_irqsave (&port->port_lock, flags);
+	down (&port->sem);
 
 	--port->open_count;
 
@@ -801,7 +807,7 @@
 		port->open_count = 0;
 	}
 
-	spin_unlock_irqrestore (&port->port_lock, flags);
+	up (&port->sem);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -809,7 +815,6 @@
 static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
-	unsigned long flags;
 	int result;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
@@ -826,7 +831,6 @@
 			return (0);
 		}
 
-		spin_lock_irqsave (&port->port_lock, flags);
 		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
 		if (from_user) {
@@ -849,14 +853,12 @@
 
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb);
-		if (result) {
+		if (result)
 			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
-			spin_unlock_irqrestore (&port->port_lock, flags);
-			return 0;
-		}
+		else
+			result = count;
 
-		spin_unlock_irqrestore (&port->port_lock, flags);
-		return (count);
+		return result;
 	}
 	
 	/* no bulk out, so return 0 bytes written */
@@ -871,9 +873,10 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	if (serial->num_bulk_out)
+	if (serial->num_bulk_out) {
 		if (port->write_urb->status != -EINPROGRESS)
 			room = port->bulk_out_size;
+	}
 	
 	dbg(__FUNCTION__ " - returns %d", room);
 	return (room);
@@ -887,9 +890,10 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	if (serial->num_bulk_out)
+	if (serial->num_bulk_out) {
 		if (port->write_urb->status == -EINPROGRESS)
 			chars = port->write_urb->transfer_buffer_length;
+	}
 
 	dbg (__FUNCTION__ " - returns %d", chars);
 	return (chars);
@@ -1091,6 +1095,33 @@
 		}
 	}
 	
+#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
+	/* BEGIN HORRIBLE HACK FOR PL2303 */ 
+	/* this is needed due to the looney way its endpoints are set up */
+	if (ifnum == 1) {
+		if (((dev->descriptor.idVendor == PL2303_VENDOR_ID) &&
+		     (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) ||
+		    ((dev->descriptor.idVendor == ATEN_VENDOR_ID) &&
+		     (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) {
+			/* check out the endpoints of the other interface*/
+			interface = &dev->actconfig->interface[ifnum ^ 1];
+			iface_desc = &interface->altsetting[0];
+			for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
+				endpoint = &iface_desc->endpoint[i];
+				if ((endpoint->bEndpointAddress & 0x80) &&
+				    ((endpoint->bmAttributes & 3) == 0x03)) {
+					/* we found a interrupt in endpoint */
+					dbg("found interrupt in for Prolific device on separate interface");
+					interrupt_pipe = HAS;
+					interrupt_in_endpoint[num_interrupt_in] = endpoint;
+					++num_interrupt_in;
+				}
+			}
+		}
+	}
+	/* END HORRIBLE HACK FOR PL2303 */
+#endif
+	
 	/* verify that we found all of the endpoints that we need */
 	if (!((interrupt_pipe & type->needs_interrupt_in) &&
 	      (bulk_in_pipe & type->needs_bulk_in) &&
@@ -1222,7 +1253,7 @@
 		port->magic = USB_SERIAL_PORT_MAGIC;
 		port->tqueue.routine = port_softint;
 		port->tqueue.data = port;
-		spin_lock_init (&port->port_lock);
+		init_MUTEX (&port->sem);
 	}
 	
 	/* initialize the devfs nodes for this device and let the user know what ports we are bound to */
@@ -1395,8 +1426,7 @@
 		return -1;
 	}
 
-	info(DRIVER_VERSION " " DRIVER_AUTHOR);
-	info(DRIVER_DESC);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
 
 	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)