USB: ch341 serial: fix port number changed after resume
authorMing Lei <tom.leiming@gmail.com>
Fri, 20 Feb 2009 13:23:09 +0000 (21:23 +0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 24 Mar 2009 23:20:36 +0000 (16:20 -0700)
This patch fixes the following bug:
.plug ch341 usb serial port into a hub port;
.ch341 driver bound to the device and /dev/ttyUSB0 comes
.open /dev/ttyUSB0 by minicom and we can use the serial successfully
.suspend the ch341 usb serial device(such as: echo suspend > power/level)
.resume the ch341 usb serial device (such as: echo on > power/level)
.new port /dev/ttyUSB1 comes ,and the original /dev/ttyUSB0 still exists,
but is no longer usable by minicom

The patch adds suspend and resume callback to ch341 usb driver to prevent it
from unbinding during suspend. The /dev/ttyUSB0 is not released until being
closed, so /dev/ttyUSB1 comes after resume, and the original /dev/ttyUSB0 is
no longer usable by minicom. It is really a mess for a minicom user.

This patch also adds the reset_resume callback to make it usable after resuming
from STR or hibernation, for generally STR or hibernation will make the vbus
of root-hub lost.

Finally enable the driver's supports_autosuspend, for the device is in working
order with it.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/ch341.c

index d5ea679e169811fb1f85229e3bbaf16319763f77..ab4cc277aa659be685a154c6a5024cf02f14eba9 100644 (file)
@@ -529,12 +529,34 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
        return result;
 }
 
+
+static int ch341_reset_resume(struct usb_interface *intf)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_serial *serial = NULL;
+       struct ch341_private *priv;
+
+       serial = usb_get_intfdata(intf);
+       priv = usb_get_serial_port_data(serial->port[0]);
+
+       /*reconfigure ch341 serial port after bus-reset*/
+       ch341_configure(dev, priv);
+
+       usb_serial_resume(intf);
+
+       return 0;
+}
+
 static struct usb_driver ch341_driver = {
        .name           = "ch341",
        .probe          = usb_serial_probe,
        .disconnect     = usb_serial_disconnect,
+       .suspend        = usb_serial_suspend,
+       .resume         = usb_serial_resume,
+       .reset_resume   = ch341_reset_resume,
        .id_table       = id_table,
        .no_dynamic_id  = 1,
+       .supports_autosuspend = 1,
 };
 
 static struct usb_serial_driver ch341_device = {