How to detect current power mode of USB HC

I’d like to find some way how to detect if USB HC to which our USB 1.1 is attached is sleeping or not. Ideally directly from the USB driver for this device and interesting is actual state, not possibilities.

Strange request, I know. We’re trying to find a quick workaround which’d mitigate Vista UHCI driver bug which causes long (up to 1024 ms) reaction to remote wakeup from the device when device is suspended and HC isn’t. When HC is really suspended everything works well. Currently, I’m able to detect if HC (well, all HCs in system) is allowed to suspend but any other device attached to the same HC can cause it doesn’t really suspend. If I’m able to detect the actual state, I would know if I can afford to really suspend the device.

Real solution is to get fix from MS. I already made a PSS request but in my experience it is just start of long and painful task. Our customers want some solutions faster so we’re examining even crazy possibilities. The bug makes our device virtually useless and current solution i.e. disable device suspend completely, isn’t acceptable for our customers.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> Real solution is to get fix from MS. I already made a PSS request but in

my experience it is just start of long and painful task. Our customers
want some solutions faster so we’re examining even crazy possibilities.
The bug makes our device virtually useless and current solution i.e.
disable device suspend completely, isn’t acceptable for our customers.

Michal,

There are only two USB 1.x controller types: UHCI and OHCI. If your driver
knows the IO location of the HC and its type the driver can just read the
status/control/command register of the HC and check the right bit(s). For
example UHCI has ‘Run/Stop’ and ‘Enter Global Suspend Mode’ bits in its
Command register (Base + (00-01h)).

Touching IO resources that do not belong to your device/driver is a bad idea
(for example, HW can be relocated/disabled/replaced under you, etc.) but you
are open to crazy solutions.

Dmitriy Budko
VMware

Dmitriy,

thanks for the idea. The problem occurs at UHCI controllers only and my driver already knows to which type of HC is the device connected. But it doesn’t know IO location of the HC – do you know how it could get it? I guess reading registers should be relatively safe and we could afford it until MS makes the fix.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]


From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of Dmitriy Budko[SMTP:xxxxx@vmware.com]
Reply To: Windows System Software Devs Interest List
Sent: Wednesday, February 21, 2007 11:13 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How to detect current power mode of USB HC

> Real solution is to get fix from MS. I already made a PSS request but in
> my experience it is just start of long and painful task. Our customers
> want some solutions faster so we’re examining even crazy possibilities.
> The bug makes our device virtually useless and current solution i.e.
> disable device suspend completely, isn’t acceptable for our customers.

Michal,

There are only two USB 1.x controller types: UHCI and OHCI. If your driver
knows the IO location of the HC and its type the driver can just read the
status/control/command register of the HC and check the right bit(s). For
example UHCI has ‘Run/Stop’ and ‘Enter Global Suspend Mode’ bits in its
Command register (Base + (00-01h)).

Touching IO resources that do not belong to your device/driver is a bad idea
(for example, HW can be relocated/disabled/replaced under you, etc.) but you
are open to crazy solutions.

Dmitriy Budko
VMware


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

I don’t see an easy way to reliably get the IO base of an HC.
Having an HC filter driver and watching/filtering resource PnP IOCTLs will
work but it’s too complicated.

I have other ideas:

  1. Call USBPORT_QueryBusTime twice 1 ms apart and see is the HC running or
    not. It also can be used to uniquely identify all HCs in the system.

  2. Send IOCTL_USB_USER_REQUEST with USBUSER_GET_POWER_STATE_MAP opcode. It
    returns USB_POWER_INFO struct that has WDMUSB_POWER_STATE
    HcDevicePowerState.

Dmitriy Budko
VMware

Dmitriy,

thanks for the idea. The problem occurs at UHCI controllers only and my
driver already knows to which type of HC is the device connected. But it
doesn’t know IO location of the HC – do you know how it could get it? I
guess reading registers should be relatively safe and we could afford it
until MS makes the fix.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> ----------
> From: xxxxx@lists.osr.com[SMTP:bounce-278877-
xxxxx@lists.osr.com] on behalf of Dmitriy Budko[SMTP:xxxxx@vmware.com]
> Reply To: Windows System Software Devs Interest List
> Sent: Wednesday, February 21, 2007 11:13 PM
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] How to detect current power mode of USB HC
>
> > Real solution is to get fix from MS. I already made a PSS request but
in
> > my experience it is just start of long and painful task. Our customers
> > want some solutions faster so we’re examining even crazy
possibilities.
> > The bug makes our device virtually useless and current solution i.e.
> > disable device suspend completely, isn’t acceptable for our customers.
>
> Michal,
>
> There are only two USB 1.x controller types: UHCI and OHCI. If your
driver
> knows the IO location of the HC and its type the driver can just read
the
> status/control/command register of the HC and check the right bit(s).
For
> example UHCI has ‘Run/Stop’ and ‘Enter Global Suspend Mode’ bits in its
> Command register (Base + (00-01h)).
>
> Touching IO resources that do not belong to your device/driver is a bad
idea
> (for example, HW can be relocated/disabled/replaced under you, etc.) but
you
> are open to crazy solutions.
>
>
> Dmitriy Budko
> VMware
>

> ----------

From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of Dmitriy Budko[SMTP:xxxxx@vmware.com]
Reply To: Windows System Software Devs Interest List
Sent: Thursday, February 22, 2007 5:20 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How to detect current power mode of USB HC

  1. Call USBPORT_QueryBusTime twice 1 ms apart and see is the HC running or
    not.

I already found and tested this way and it seems to work. I have to find some good strategy because HC is running about 700 ms more after my device suspends but main problem seems to be solved. Thanks anyway.

It also can be used to uniquely identify all HCs in the system.

I don’t quite understand this part. Do you mean counters for all HCs are always different enough? However, my driver has interface to HC to which it is attached (QUERY_INTERFACE IRP).

  1. Send IOCTL_USB_USER_REQUEST with USBUSER_GET_POWER_STATE_MAP opcode. It
    returns USB_POWER_INFO struct that has WDMUSB_POWER_STATE
    HcDevicePowerState.

Are these IOCTLs available from kernel mode, too? Maybe silly question but I see them the first time :slight_smile:

BTW, have you tried IOCTL_INTERNAL_USB_REQ_GLOBAL_SUSPEND?

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> > 1) Call USBPORT_QueryBusTime twice 1 ms apart and see is the HC running

or
> not.
>
I already found and tested this way and it seems to work. I have to find
some good strategy because HC is running about 700 ms more after my device
suspends but main problem seems to be solved. Thanks anyway.

> It also can be used to uniquely identify all HCs in the system.
>
I don’t quite understand this part. Do you mean counters for all HCs are
always different enough? However, my driver has interface to HC to which
it is attached (QUERY_INTERFACE IRP).

Yes, I suspect that counters for all HCs are different enough or at least the
exact times of counter updates are different. It can be used for the
following method:

Somehow enumerate all PCI devices in the system. As the result you’ll have
the list of HCs with their IO bases. After that you’ll need to somehow
correlate enumerated HCs with the interfaces and unique bus frame counters
can help here.

> 2) Send IOCTL_USB_USER_REQUEST with USBUSER_GET_POWER_STATE_MAP opcode.
It
> returns USB_POWER_INFO struct that has WDMUSB_POWER_STATE
> HcDevicePowerState.
>
Are these IOCTLs available from kernel mode, too? Maybe silly question but
I see them the first time :slight_smile:

The docs say that they are available from kernel mode:
http://msdn2.microsoft.com/en-us/library/aa476224.aspx

BTW, have you tried IOCTL_INTERNAL_USB_REQ_GLOBAL_SUSPEND?

No, I haven’t. I don’t do active USB development these days.

Dmitriy Budko
VMware