patch-2.4.19 linux-2.4.19/drivers/usb/serial/whiteheat.c

Next file: linux-2.4.19/drivers/usb/serial/whiteheat_fw.h
Previous file: linux-2.4.19/drivers/usb/serial/visor.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/drivers/usb/serial/whiteheat.c linux-2.4.19/drivers/usb/serial/whiteheat.c
@@ -88,7 +88,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1"
+#define DRIVER_VERSION "v1.2"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
 
@@ -128,8 +128,9 @@
 static void whiteheat_set_termios	(struct usb_serial_port *port, struct termios * old);
 static void whiteheat_throttle		(struct usb_serial_port *port);
 static void whiteheat_unthrottle	(struct usb_serial_port *port);
-static int  whiteheat_startup		(struct usb_serial *serial);
-static void whiteheat_shutdown		(struct usb_serial *serial);
+static int  whiteheat_fake_startup	(struct usb_serial *serial);
+static int  whiteheat_real_startup	(struct usb_serial *serial);
+static void whiteheat_real_shutdown	(struct usb_serial *serial);
 
 static struct usb_serial_device_type whiteheat_fake_device = {
 	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
@@ -141,7 +142,7 @@
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
 	num_ports:		1,
-	startup:		whiteheat_startup	
+	startup:		whiteheat_fake_startup,
 };
 
 static struct usb_serial_device_type whiteheat_device = {
@@ -160,7 +161,8 @@
 	unthrottle:		whiteheat_unthrottle,
 	ioctl:			whiteheat_ioctl,
 	set_termios:		whiteheat_set_termios,
-	shutdown:		whiteheat_shutdown,
+	startup:		whiteheat_real_startup,
+	shutdown:		whiteheat_real_shutdown,
 };
 
 struct whiteheat_private {
@@ -539,7 +541,7 @@
  - device renumerated itself and comes up as new device id with all
    firmware download completed.
 */
-static int  whiteheat_startup (struct usb_serial *serial)
+static int  whiteheat_fake_startup (struct usb_serial *serial)
 {
 	int response;
 	const struct whiteheat_hex_record *record;
@@ -598,9 +600,68 @@
 }
 
 
-static void whiteheat_shutdown (struct usb_serial *serial)
+static int  whiteheat_real_startup (struct usb_serial *serial)
 {
-	struct usb_serial_port 		*command_port;
+	struct whiteheat_hw_info *hw_info;
+	int pipe;
+	int ret;
+	int alen;
+	__u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 };
+	__u8 result[sizeof(*hw_info) + 1];
+
+	pipe = usb_rcvbulkpipe (serial->dev, 7);
+	usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
+	/*
+	 * We ignore the return code. In the case where rmmod/insmod is
+	 * performed with a WhiteHEAT connected, the above times out
+	 * because the endpoint is already prepped, meaning the below succeeds
+	 * regardless. All other cases the above succeeds.
+	 */
+
+	pipe = usb_sndbulkpipe (serial->dev, 7);
+	ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, 2 * HZ);
+	if (ret) {
+		err("%s: Couldn't send command [%d]", serial->type->name, ret);
+		goto error_out;
+	} else if (alen != sizeof(command)) {
+		err("%s: Send command incomplete [%d]", serial->type->name, alen);
+		goto error_out;
+	}
+
+	pipe = usb_rcvbulkpipe (serial->dev, 7);
+	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
+	if (ret) {
+		err("%s: Couldn't get results [%d]", serial->type->name, ret);
+		goto error_out;
+	} else if (alen != sizeof(result)) {
+		err("%s: Get results incomplete [%d]", serial->type->name, alen);
+		goto error_out;
+	} else if (result[0] != command[0]) {
+		err("%s: Command failed [%d]", serial->type->name, result[0]);
+		goto error_out;
+	}
+
+	hw_info = (struct whiteheat_hw_info *)&result[1];
+
+	info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+	     DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
+
+	return 0;
+
+error_out:
+	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
+	/*
+	 * Return that we've claimed the interface. A failure here may be
+	 * due to interception by the command_callback routine or other
+	 * causes that don't mean that the firmware isn't running. This may
+	 * change in the future. Probably should actually.
+	 */
+	return 0;
+}
+
+static void whiteheat_real_shutdown (struct usb_serial *serial)
+{
+	struct usb_serial_port *command_port;
 	int i;
 
 	dbg(__FUNCTION__);
@@ -623,8 +684,6 @@
 }
 
 
-
-
 static void set_command (struct usb_serial_port *port, unsigned char state, unsigned char command)
 {
 	struct whiteheat_rdb_set rdb_command;
@@ -660,7 +719,7 @@
 {
 	usb_serial_register (&whiteheat_fake_device);
 	usb_serial_register (&whiteheat_device);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
 

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