Search code examples
androidlinuxlinux-kernelusbdevice-driver

How do kernel get to know when a USB device goes to low power mode by itself (not initiated by host)?


One USB device has the ability to go into low power mode(supports suspend and resume).

The host also can initiate suspend and resume for the device, in this case, the host knows about device state.

Scenario is:

  • Device initiate low power mode.
  • Host driver Want to access this information about low power state of device
  • How can a driver get this information from Linux Kernel?

Solution

  • As per USB specification, a USB device cannot suspend a link to USB host. Only host can suspend a link. Also suspend(U3) is not same as low power mode(U1/U2). A device can start switching to low power mode by negotiating with host but not suspend.

    Now lets consider you meant low power mode (U1/U2), then host driver has no way to know when the ports are switching to low power mode initiated by device as there will be no event for that. You need to monitor the link state your self to see if the link has switched to low power mode.

    As far as I know, there is one API which is used to to get link state of device connected to a hub.

    static void xhci_hub_report_link_state(struct xhci_hcd *xhci,
                    u32 *status, u32 status_reg)
    

    This API you can use to track the link state of a device which is connected via external hub. But there is no API which can be used to read root hub port link state. If host controller driver exposes any interface, then that can be used.

    See the dwc3 controller code which exposes a debugfs interface which can be used to read link state.

    path - usb/dwc3/debugfs.c

    API -

    static int dwc3_link_state_show(struct seq_file *s, void *unused)
    

    PS - I have considered you have XHCI controller. But its almost same for EHCI controller too. Device can never suspend USB link.