Hi,
this implements autosuspend for the trancevibrator driver. I hope this can
serve as a model for PID devices. Could you please test this patch?
Regards
Oliver
----
--- linux-2.6.24-ser/drivers/usb/misc/trancevibrator.c.alt2 2008-01-30
16:18:27.000000000 +0100
+++ linux-2.6.24-ser/drivers/usb/misc/trancevibrator.c 2008-01-30
17:10:43.000000000 +0100
@@ -71,6 +71,12 @@ static ssize_t set_speed(struct device *
dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
+ if (!old) {
+ /* device asleep, must be woken */
+ retval = usb_autopm_get_interface(intf);
+ if (retval < 0)
+ goto error_bail_out;
+ }
/* Set speed */
retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
0x01, /* vendor request: set speed */
@@ -78,9 +84,17 @@ static ssize_t set_speed(struct device *
tv->speed, /* speed value */
0, NULL, 0, USB_CTRL_GET_TIMEOUT);
if (retval) {
+error_bail_out:
tv->speed = old;
dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
return retval;
+ } else {
+ /*
+ * the device can go back to sleep,
+ * if it isn't vibrating
+ */
+ if (!temp)
+ usb_autopm_put_interface(intf);
}
return count;
}
@@ -128,12 +142,49 @@ static void tv_disconnect(struct usb_int
kfree(dev);
}
+static int tv_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct trancevibrator *tv = usb_get_intfdata(intf);
+ int retval;
+
+ if (tv->udev->auto_pm)
+ return 0;
+
+ /* Set speed to 0 to stop vibrating */
+ retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
+ 0x01, /* vendor request: set speed */
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ 0, /* speed value */
+ 0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+
+ return retval;
+}
+
+static int tv_resume(struct usb_interface *intf)
+{
+ struct trancevibrator *tv = usb_get_intfdata(intf);
+ int retval;
+
+ if (tv->udev->auto_pm)
+ return 0;
+
+ retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
+ 0x01, /* vendor request: set speed */
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ tv->speed, /* restore speed value */
+ 0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+ return retval;
+}
+
/* USB subsystem object */
static struct usb_driver tv_driver = {
.name = "trancevibrator",
.probe = tv_probe,
.disconnect = tv_disconnect,
+ .suspend = tv_suspend,
+ .resume = tv_resume,
.id_table = id_table,
+ .supports_autosuspend = 1,
};
static int __init tv_init(void)
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html