patch-2.4.0-test10 linux/drivers/usb/serial/whiteheat.c

Next file: linux/drivers/usb/serial/whiteheat.h
Previous file: linux/drivers/usb/serial/visor.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test9/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
@@ -11,6 +11,18 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (10/05/2000) gkh
+ *	Fixed bug with urb->dev not being set properly, now that the usb
+ *	core needs it.
+ * 
+ * (10/03/2000) smd
+ *	firmware is improved to guard against crap sent to device
+ *	firmware now replies CMD_FAILURE on bad things
+ *	read_callback fix you provided for private info struct
+ *	command_finished now indicates success or fail
+ *	setup_port struct now packed to avoid gcc padding
+ *	firmware uses 1 based port numbering, driver now handles that
+ *
  * (09/11/2000) gkh
  *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
  *
@@ -148,8 +160,11 @@
 
 static void command_port_read_callback (struct urb *urb)
 {
-	struct whiteheat_private *info = (struct whiteheat_private *)urb->context;
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct whiteheat_private *info;
 	unsigned char *data = urb->transfer_buffer;
+	int result;
 
 	dbg (__FUNCTION__);
 
@@ -158,15 +173,39 @@
 		return;
 	}
 
+	if (!serial) {
+		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		return;
+	}
+	
 	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
+	info = (struct whiteheat_private *)port->private;
+	if (!info) {
+		dbg (__FUNCTION__ " - info is NULL, exiting.");
+		return;
+	}
+
 	/* right now, if the command is COMMAND_COMPLETE, just flip the bit saying the command finished */
 	/* in the future we're going to have to pay attention to the actual command that completed */
 	if (data[0] == WHITEHEAT_CMD_COMPLETE) {
-		info->command_finished = TRUE;
+		info->command_finished = WHITEHEAT_CMD_COMPLETE;
+		wake_up_interruptible(&info->wait_command);
 	}
 	
-	return;
+	if (data[0] == WHITEHEAT_CMD_FAILURE) {
+		info->command_finished = WHITEHEAT_CMD_FAILURE;
+		wake_up_interruptible(&info->wait_command);
+	}
+	
+	/* Continue trying to always read */
+	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,
+		      command_port_read_callback, port);
+	result = usb_submit_urb(port->read_urb);
+	if (result)
+		dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 }
 
 
@@ -187,6 +226,7 @@
 	transfer_buffer[0] = command;
 	memcpy (&transfer_buffer[1], data, datasize);
 	port->write_urb->transfer_buffer_length = datasize + 1;
+	port->write_urb->dev = serial->dev;
 	if (usb_submit_urb (port->write_urb)) {
 		dbg (__FUNCTION__" - submit urb failed");
 		return -1;
@@ -203,6 +243,16 @@
 		return -1;
 	}
 
+	if (info->command_finished == WHITEHEAT_CMD_FAILURE) {
+		dbg (__FUNCTION__ " - command failed.");
+		return -1;
+	}
+
+	if (info->command_finished == WHITEHEAT_CMD_COMPLETE) {
+		dbg (__FUNCTION__ " - command completed.");
+		return 0;
+	}
+
 	return 0;
 }
 
@@ -212,6 +262,7 @@
 	struct whiteheat_min_set	open_command;
 	struct usb_serial_port 		*command_port;
 	struct whiteheat_private	*info;
+	int				result;
 
 	dbg(__FUNCTION__" - port %d", port->number);
 
@@ -234,15 +285,20 @@
 		command_port->private = info;
 		command_port->write_urb->complete = command_port_write_callback;
 		command_port->read_urb->complete = command_port_read_callback;
-		usb_submit_urb (command_port->read_urb);	
+		command_port->read_urb->dev = port->serial->dev;
+		command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */
+		usb_submit_urb (command_port->read_urb);
 	}
 	
 	/* Start reading from the device */
-	if (usb_submit_urb(port->read_urb))
-		dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
+	port->read_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->read_urb);
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 
 	/* send an open port command */
-	open_command.port = port->number - port->serial->minor;
+	/* firmware uses 1 based port numbering */
+	open_command.port = port->number - port->serial->minor + 1;
 	whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
 
 	/* Need to do device specific setup here (control lines, baud rate, etc.) */
@@ -261,7 +317,8 @@
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
 	/* send a close command to the port */
-	close_command.port = port->number - port->serial->minor;
+	/* firmware uses 1 based port numbering */
+	close_command.port = port->number - port->serial->minor + 1;
 	whiteheat_send_cmd (port->serial, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
 
 	/* Need to change the control lines here */
@@ -303,6 +360,10 @@
 		return;
 	}
 	
+	/* set the port number */
+	/* firmware uses 1 based port numbering */
+	port_settings.port = port->number + 1;
+
 	/* get the byte size */
 	switch (cflag & CSIZE) {
 		case CS5:	port_settings.bits = 5;   break;
@@ -337,10 +398,10 @@
 	else
 		port_settings.hflow = 0;
 	dbg(__FUNCTION__ " - hardware flow control = %s %s %s %s",
-	    (port_settings.hflow | WHITEHEAT_CTS_FLOW) ? "CTS" : "",
-	    (port_settings.hflow | WHITEHEAT_RTS_FLOW) ? "RTS" : "",
-	    (port_settings.hflow | WHITEHEAT_DSR_FLOW) ? "DSR" : "",
-	    (port_settings.hflow | WHITEHEAT_DTR_FLOW) ? "DTR" : "");
+	    (port_settings.hflow & WHITEHEAT_CTS_FLOW) ? "CTS" : "",
+	    (port_settings.hflow & WHITEHEAT_RTS_FLOW) ? "RTS" : "",
+	    (port_settings.hflow & WHITEHEAT_DSR_FLOW) ? "DSR" : "",
+	    (port_settings.hflow & WHITEHEAT_DTR_FLOW) ? "DTR" : "");
 	
 	/* determine software flow control */
 	if (I_IXOFF(port->tty))
@@ -485,7 +546,8 @@
 	struct whiteheat_rdb_set rdb_command;
 	
 	/* send a set rts command to the port */
-	rdb_command.port = port->number - port->serial->minor;
+	/* firmware uses 1 based port numbering */
+	rdb_command.port = port->number - port->serial->minor + 1;
 	rdb_command.state = state;
 
 	whiteheat_send_cmd (port->serial, command, (__u8 *)&rdb_command, sizeof(rdb_command));

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