patch-2.3.35 linux/drivers/usb/usb-serial.c

Next file: linux/drivers/usb/usb.c
Previous file: linux/drivers/usb/usb-core.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
@@ -14,6 +14,13 @@
  *
  * See README.serial for more information on using this driver.
  * 
+ * version 0.2.3 (12/21/99) gkh
+ *	Added initial support for the Connect Tech WhiteHEAT converter.
+ *	Incremented the number of ports in expectation of getting the
+ *	WhiteHEAT to work properly (4 ports per connection).
+ *	Added notification on insertion and removal of what port the
+ *	device is/was connected to (and what kind of device it was).
+ *
  * version 0.2.2 (12/16/99) gkh
  *	Changed major number to the new allocated number. We're legal now!
  *
@@ -88,12 +95,12 @@
 #define BELKIN_SERIAL_CONVERTER		0x8007
 #define PERACOM_VENDOR_ID		0x0565
 #define PERACOM_SERIAL_CONVERTER	0x0001
+#define CONNECT_TECH_VENDOR_ID		0x0710
+#define CONNECT_TECH_WHITE_HEAT_ID	0x0001
 
 
 #define SERIAL_MAJOR	188	/* Nice legal number now */
-
-#define NUM_PORTS	4	/* Have to pick a number for now. Need to look */
-				/* into dynamically creating them at insertion time. */
+#define NUM_PORTS	16	/* Actually we are allowed 255, but this is good for now */
 
 
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
@@ -119,26 +126,6 @@
 static void serial_unthrottle (struct tty_struct * tty);
 
 
-/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
-static int etek_serial_open (struct tty_struct *tty, struct file * filp);
-static void etek_serial_close (struct tty_struct *tty, struct file * filp);
-static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int etek_write_room (struct tty_struct *tty);
-static int etek_chars_in_buffer (struct tty_struct *tty);
-static void etek_throttle (struct tty_struct * tty);
-static void etek_unthrottle (struct tty_struct * tty);
-
-
-/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
-static int generic_serial_open (struct tty_struct *tty, struct file * filp);
-static void generic_serial_close (struct tty_struct *tty, struct file * filp);
-static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int generic_write_room (struct tty_struct *tty);
-static int generic_chars_in_buffer (struct tty_struct *tty);
-
-
 /* This structure defines the individual serial converter. */
 struct usb_serial_device_type {
 	char	*name;
@@ -157,10 +144,17 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
-
 };
 
 
+/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
+static int  etek_serial_open		(struct tty_struct *tty, struct file *filp);
+static void etek_serial_close		(struct tty_struct *tty, struct file *filp);
+static int  etek_serial_write		(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void etek_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  etek_write_room		(struct tty_struct *tty);
+static int  etek_chars_in_buffer	(struct tty_struct *tty);
+
 /* All of the device info needed for the Belkin Serial Converter */
 static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
 static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER;
@@ -177,8 +171,8 @@
 	etek_serial_put_char,
 	etek_write_room,
 	etek_chars_in_buffer,
-	etek_throttle,
-	etek_unthrottle
+	NULL,
+	NULL
 };
 
 /* All of the device info needed for the Peracom Serial Converter */
@@ -197,10 +191,50 @@
 	etek_serial_put_char,
 	etek_write_room,
 	etek_chars_in_buffer,
-	etek_throttle,
-	etek_unthrottle
+	NULL,
+	NULL
+};
+
+
+/* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int  whiteheat_serial_open	(struct tty_struct *tty, struct file *filp);
+static void whiteheat_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  whiteheat_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void whiteheat_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  whiteheat_write_room	(struct tty_struct *tty);
+static int  whiteheat_chars_in_buffer	(struct tty_struct *tty);
+static void whiteheat_throttle		(struct tty_struct *tty);
+static void whiteheat_unthrottle	(struct tty_struct *tty);
+
+/* All of the device info needed for the Connect Tech WhiteHEAT */
+static __u16	connecttech_vendor_id			= CONNECT_TECH_VENDOR_ID;
+static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
+static struct usb_serial_device_type whiteheat_device = {
+	"Connect Tech - WhiteHEAT",
+	&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	&connecttech_whiteheat_product_id,	/* the White Heat product id */
+	DONT_CARE,		/* don't have to have an interrupt in endpoint */
+	DONT_CARE,		/* don't have to have a bulk in endpoint */
+	DONT_CARE,		/* don't have to have a bulk out endpoint */
+	whiteheat_serial_open,
+	whiteheat_serial_close,
+	whiteheat_serial_write,
+	whiteheat_serial_put_char,
+	whiteheat_write_room,
+	whiteheat_chars_in_buffer,
+	whiteheat_throttle,
+	whiteheat_unthrottle
 };
 
+
+/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+static int  generic_serial_open		(struct tty_struct *tty, struct file *filp);
+static void generic_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  generic_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void generic_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  generic_write_room		(struct tty_struct *tty);
+static int  generic_chars_in_buffer	(struct tty_struct *tty);
+
 /* All of the device info needed for the Generic Serial Converter */
 static struct usb_serial_device_type generic_device = {
 	"Generic",
@@ -225,6 +259,7 @@
    entry is NULL. */
 static struct usb_serial_device_type *usb_serial_devices[] = {
 	&generic_device,
+	&whiteheat_device,
 	&belkin_device,
 	&peracom_device,
 	NULL
@@ -238,6 +273,7 @@
 	void *				irq_handle;
 	unsigned int			irqpipe;
 	struct tty_struct *		tty;		/* the coresponding tty for this device */
+	unsigned char			number;
 	char				present;
 	char				active;
 
@@ -292,7 +328,7 @@
        	unsigned char* data = buffer;
 	int i;
 
-	debug_info("USB serial: serial_read_irq\n");
+	debug_info("USB Serial: serial_read_irq\n");
 
 #ifdef SERIAL_DEBUG
 	if (count) {
@@ -340,9 +376,11 @@
 }
 
 
+#if 0
+/* we will need this soon... removed for now to keep the compile warnings down */
 static int usb_serial_irq (int state, void *buffer, int len, void *dev_id)
 {
-//	struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
+	struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
 
 	debug_info("USB Serial: usb_serial_irq\n");
 
@@ -352,7 +390,7 @@
 
 	return (1);
 }
-
+#endif
 
 
 
@@ -753,11 +791,141 @@
 }
 
 
-static void etek_throttle (struct tty_struct * tty)
+/*****************************************************************************
+ * Connect Tech's White Heat specific driver functions
+ *****************************************************************************/
+static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("USB Serial: etek_throttle\n");
+	debug_info("USB Serial: whiteheat_serial_open\n");
+
+	if (!serial->present) {
+		debug_info("USB Serial: no device registered\n");
+		return -EINVAL;
+	}
+
+	if (serial->active) {
+		debug_info ("USB Serial: device already open\n");
+		return -EINVAL;
+	}
+	serial->active = 1;
+ 
+	/*Start reading from the device*/
+	serial->bulk_in_inuse = 1;
+	serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
+
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME!!! */
+
+	return (0);
+}
+
+
+static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	debug_info("USB Serial: whiteheat_serial_close\n");
+	
+	/* Need to change the control lines here */
+	/* FIXME */
+	
+	/* shutdown our bulk reads and writes */
+	if (serial->bulk_out_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
+		serial->bulk_out_inuse = 0;
+	}
+	if (serial->bulk_in_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
+		serial->bulk_in_inuse = 0;
+	}
+
+	/* release the irq? */
+	
+	serial->active = 0;
+}
+
+
+static int whiteheat_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	int written;
+	
+	debug_info("USB Serial: whiteheat_serial_write\n");
+
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return (0);
+	}
+
+	written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
+	  
+	if (from_user) {
+		copy_from_user(serial->bulk_out_buffer, buf, written);
+	}
+	else {
+		memcpy (serial->bulk_out_buffer, buf, written);
+	}  
+
+	/* send the data out the bulk port */
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
+
+	return (written);
+} 
+
+
+static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	
+	debug_info("USB Serial: whiteheat_serial_put_char\n");
+	
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return;
+	}
+
+	/* send the single character out the bulk port */
+	serial->bulk_out_buffer[0] = ch;
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
+
+	return;
+}
+
+
+static int whiteheat_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: whiteheat_write_room\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (0);
+	}
+
+	return (serial->bulk_out_size);
+}
+
+
+static int whiteheat_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: whiteheat_chars_in_buffer\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (serial->bulk_out_size);
+	}
+
+	return (0);
+}
+
+
+static void whiteheat_throttle (struct tty_struct * tty)
+{
+	debug_info("USB Serial: whiteheat_throttle\n");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -766,11 +934,9 @@
 }
 
 
-static void etek_unthrottle (struct tty_struct * tty)
+static void whiteheat_unthrottle (struct tty_struct * tty)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-
-	debug_info("USB Serial: etek_unthrottle\n");
+	debug_info("USB Serial: whiteheat_unthrottle\n");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -953,7 +1119,7 @@
 	while (usb_serial_devices[device_num] != NULL) {
 		type = usb_serial_devices[device_num];
 		#ifdef SERIAL_DEBUG
-			printk ("USB Serial: Looking at %s\nVendor id=%.4x\nProduct id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
+			printk ("USB Serial: Looking at %s Vendor id=%.4x Product id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
 		#endif		
 
 		/* look at the device descriptor */
@@ -1013,7 +1179,7 @@
 			    (bulk_in_pipe & type->needs_bulk_in) &&
 			    (bulk_out_pipe & type->needs_bulk_out)) {
 				/* found all that we need */
-				printk (KERN_INFO "USB serial converter detected.\n");
+				printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name);
 
 				if (0>(serial_num = Get_Free_Serial())) {
 					debug_info("USB Serial: Too many devices connected\n");
@@ -1025,6 +1191,7 @@
 			       	memset(serial, 0, sizeof(struct usb_serial_state));
 			       	serial->dev = dev;
 				serial->type = type;
+				serial->number = serial_num;
 
 				/* set up the endpoint information */
 				if (bulk_in_endpoint) {
@@ -1086,6 +1253,7 @@
 				serial->present = 1;
 				MOD_INC_USE_COUNT;
 
+				printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num);
 				return serial;
 			} else {
 				printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n");
@@ -1139,11 +1307,15 @@
 
 		serial->present = 0;
 		serial->active = 0;
+
+		printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number);
+
+	} else {
+		printk (KERN_INFO "USB Serial: device disconnected.\n");
 	}
 	
 	MOD_DEC_USE_COUNT;
 
-	printk (KERN_INFO "USB Serial: device disconnected.\n");
 }
 
 

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