# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.424 -> 1.425 # drivers/usb/serial/whiteheat.c 1.10 -> 1.11 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/04/18 greg@kroah.com 1.425 # USB whiteheat driver # # backported the 2.5 changes for the new whiteheat devices. # -------------------------------------------- # diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c --- a/drivers/usb/serial/whiteheat.c Thu Apr 18 13:53:58 2002 +++ b/drivers/usb/serial/whiteheat.c Thu Apr 18 13:53:58 2002 @@ -88,7 +88,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.1" +#define DRIVER_VERSION "v1.2" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #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; }