Hi, I can't boot 2.6.19-rc1, so here's an incomplete version of autosuspend for hid to invite comments on the basic approach.
Regards Oliver --- linux-2.6.19-rc1/drivers/usb/input/hid.h 2006-10-05 04:57:05.000000000 +0200 +++ gregtree/drivers/usb/input/hid.h 2006-10-09 15:20:21.000000000 +0200 @@ -384,6 +384,9 @@ #define HID_IN_RUNNING 3 #define HID_RESET_PENDING 4 #define HID_SUSPENDED 5 +#define HID_IN_IDLE 6 + +#define HID_IDLE_TIME 200*HZ struct hid_input { struct list_head list; @@ -408,9 +411,11 @@ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ struct timer_list io_retry; /* Retry timer */ + struct timer_list idle_timer; /* timer to determine idleness */ unsigned long stop_retry; /* Time to give up, in jiffies */ unsigned int retry_delay; /* Delay length in ms */ struct work_struct reset_work; /* Task context for resets */ + struct work_struct idle_work; /* Task context for reporting idleness */ unsigned int bufsize; /* URB buffer size */ --- linux-2.6.19-rc1/drivers/usb/input/hid-core.c 2006-10-05 04:57:05.000000000 +0200 +++ gregtree/drivers/usb/input/hid-core.c 2006-10-09 15:23:09.000000000 +0200 @@ -1009,6 +1009,8 @@ struct hid_device *hid = urb->context; int status; + /*data recieved, errors ignored as they are handled, device not idle */ + clear_bit(HID_IN_IDLE, &hid->iofl); switch (urb->status) { case 0: /* success */ hid->retry_delay = 0; @@ -1365,9 +1367,15 @@ return result; } +static void hid_check_idle(unsigned long arg); +void hid_add_idle_timer(struct hid_device *hid); +static void __hid_report_idle(void *d); + int hid_open(struct hid_device *hid) { - ++hid->open; + clear_bit(HID_IN_IDLE, &hid->iofl); + if (!hid->open++) + usb_autopm_get_interface(hid->intf); if (hid_start_in(hid)) hid_io_error(hid); return 0; @@ -1375,8 +1383,10 @@ void hid_close(struct hid_device *hid) { - if (!--hid->open) + if (!--hid->open) { usb_kill_urb(hid->urbin); + set_bit(HID_IN_IDLE, &hid->iofl); + } } #define USB_VENDOR_ID_PANJIT 0x134c @@ -1971,12 +1981,16 @@ init_waitqueue_head(&hid->wait); INIT_WORK(&hid->reset_work, hid_reset, hid); + INIT_WORK(&hid->idle_work, __hid_report_idle, intf); setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); + setup_timer(&hid->idle_timer, hid_check_idle, (unsigned long) hid); spin_lock_init(&hid->inlock); spin_lock_init(&hid->outlock); spin_lock_init(&hid->ctrllock); + set_bit(HID_IN_IDLE, &hid->iofl); + hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; hid->dev = dev; @@ -2050,6 +2064,7 @@ usb_kill_urb(hid->urbctrl); del_timer_sync(&hid->io_retry); + del_timer_sync(&hid->idle_timer); flush_scheduled_work(); if (hid->claimed & HID_CLAIMED_INPUT) @@ -2116,12 +2131,64 @@ usb_make_path(interface_to_usbdev(intf), path, 63); + if ((hid->claimed & HID_CLAIMED_INPUT) && !(hid->claimed & HID_CLAIMED_HIDDEV)) + hid_add_idle_timer(hid); + printk(": USB HID v%x.%02x %s [%s] on %s\n", hid->version >> 8, hid->version & 0xff, c, hid->name, path); return 0; } +void hid_add_idle_timer(struct hid_device *hid) +{ + hid->idle_timer.expires = jiffies + HID_IDLE_TIME; + add_timer(&hid->idle_timer); +} + +static void hid_mod_idle_timer(struct hid_device *hid) +{ + unsigned long flags; + + spin_lock_irqsave(&hid->inlock, flags); + if (usb_get_intfdata(hid->intf)) + mod_timer(&hid->idle_timer, jiffies + HID_IDLE_TIME); + spin_unlock_irqrestore(&hid->inlock, flags); +} + +static void __hid_report_idle(void *d) +{ + struct usb_interface *intf = d; + + usb_autopm_put_interface(intf); +} + +static void hid_report_idle(struct hid_device *hid) +{ + struct usb_interface *intf = hid->intf; + unsigned long flags; + + spin_lock_irqsave(&hid->inlock, flags); + if (!test_bit(HID_SUSPENDED, &hid->iofl)) + if (usb_get_intfdata(intf)) + schedule_work(&hid->idle_work); + spin_unlock_irqrestore(&hid->inlock, flags); +} + +static void hid_check_idle(unsigned long arg) +{ + struct hid_device *hid = (struct hid_device *)arg; + int state; + + state = test_and_set_bit(HID_IN_IDLE, &hid->iofl); + + if (!state) { + hid_mod_idle_timer(hid); + } else { + hid_report_idle(hid); + } +} + static int hid_suspend(struct usb_interface *intf, pm_message_t message) { struct hid_device *hid = usb_get_intfdata (intf); ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel