• AVR Freaks

USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle...

Author
rainshadowtech
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2009/03/11 20:32:16
  • Location: 0
  • Status: offline
2011/01/16 12:46:02 (permalink)
0

USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle...

I have an application/device built on a PIC18F87J50 using the CDC example code as the base and leveraging the usbser microsoft driver.

I am hoping to get the application/device to wake up a windows 7 computer.  In my steps to get there I have enabled the _RWU flag in the config descriptor.

When testing on Linux, the USBGetRemoteWakeupStatus() function returns false when the PC is operating, and true when the PC is in hibernate.

But on Windows, the USBGetRemoteWakeupStatus() function always returns false.  There is not a 'power management' tab contained on the device manager of the application/device.  And though 'powercfg' returns the device's name from a 'powercfg -devicequery wake_from_any" query, it does not show up with a 'powercfg -devicequery wake_programmable' or 'powercfg -devicequery wake_armed'.

So my multi-part question is:
Does the microsoft usbser driver support a device wakeup from the CDC usb stack?
If so, what am I missing in enabling this functionality?  Something else to look at?

Thanks for any assistance or pointers.

-stephanick



#1

7 Replies Related Threads

    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/17 00:10:26 (permalink)
    0

    Which sleep mode did you test on Windows, "Stand-by" or "Hibernate"?
    Windows behavior differs on these two modes.

    USBGetRemoteWakeupStatus() returns RemoteWakeup flag.
    This flag is set by Set_Featrue( REMOTE_WAKE_UP ) request by host.
    And the flag is dropped by Clear_Featrue( REMOTE_WAKE_UP )

    To a remote-wakeup capable device, (ie. D5 bit of bmAttributes on config descriptor is enabled)
    Stand-By mode
    - Before going to Stand-By, Windows put Set_Featrue( REMOTE_WAKE_UP )
    - Just after recovering from Stand-By, Windows put Clear_Featrue( REMOTE_WAKE_UP )

    Hibernate mode
    - Before going to Hibernate, Windows put no request, regardless of remote-wakeup capability.
    - Just after recovering from Hibernate, Windows put no request.

    In Hibernate mode, Windows don't wake up by remote wakeup.

    These modes are switched using Power Options on Control Panel,
    if your PC supports both modes.

    OR
    using command line,

    > powercfg -h off

    Tsuneo
    post edited by chinzei - 2011/01/17 01:10:16
    #2
    rainshadowtech
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2009/03/11 20:32:16
    • Location: 0
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/18 00:49:08 (permalink)
    0
    Thanks for the additional information regarding windows behavior.

    To answer your question -- I did try both both 'sleep' and 'hibernate'.  With 'S1-only' enabled in bios, I can sleep or hibernate, and the computer can be woken up with a USB mouse click from 'sleep' but not from 'hibernate'.  With 'S3-only' enabled in bios, only the sleep option appears and it acts pretty much like a hibernate (can't wake up with a mouse click).

    But when in S1 sleep mode, USBGetRemoteWakeupStatus() still continues to report FALSE, and a call to USBCBSendResume() will not wake the computer back up.  Admittedly, I haven't validated the timing of USBResumeControl to be between 1 and 15ms, but I did turn optimization off and declared the counter to be volatile so the loop wouldn't be optimized out.


    So let me know if I missed anything here.  I guess what I need now is some assurance that the CDC example software stack (emulating a serial COM port) when paired with the usbser MS driver is actually capable of waking a Win7 computer from S1 sleep.  If that is the case, I will continue to experiment, possibly with a different motherboard.


    Thanks much,
    -stephanick




    #3
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/19 10:04:48 (permalink)
    0
    Your observation was reproduced on my side, too.
    I burnt a PIC18F87J50 PIM with "USB Device - CDC - Basic Demo" example, modified just the bmAttributes on config descriptor for remote wakeup. As you said, Windows 7 (x64) don't put Set_Featrue/Clear_Featrue around Stand-By.

    I investigated more on remote wakeup support on Windows.
    Each USB client driver is involved in remote wakeup implementation (1).
    Therefore, the support of remote wakeup depends on the coding of each class driver.
    Windows don't support remote wakeup on Mass-Storage (2), but on CCID (3) and KMDF drivers (including WinUSB)
    HID obviously supports it, though I can't find any document on MS web pages yet.

    Unfortunately, any document on CDC is not found yet.


    [References]
    (1) Supporting Devices that Have Wake-Up Capabilities
    http://msdn.microsoft.com...3907%28v=vs.85%29.aspx

    (2) USB Storage - FAQ for Driver and Hardware Developers
    http://www.microsoft.com/...onnect/usb/usbfaq.mspx
    Usbstor.sys and Power Management
    Q. Should my USB device set the remote wake bit on the USB storage device’s configuration descriptor?
    The Windows USB storage driver does not currently use the remote wake field of the device.


    (3) Microsoft Class Drivers for USB CCID Smart Cards
    http://www.microsoft.com/...martcard/usb_ccid.mspx
    Driver support for system wake from suspend/hibernate state on card insertion (even if the reader sets the remote wake bit). This feature may be made available as more smart-card readers provide remote wake functionality.

    (4) Selective Suspend in USB Drivers
    http://download.microsoft...a/USB_select-susp.docx
    Remote Wake Support for KMDF Drivers

    Tsuneo
    #4
    rainshadowtech
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2009/03/11 20:32:16
    • Location: 0
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/23 10:09:29 (permalink)
    0
    Continuing to plug away at example CDC driver stuff.  Two topics here:

    1)
    I got a tip that the windows inf file can have an effect on remote wakeup, and that a setting in it could solve the problem.  Specifically, the registry entry:
    HKR,,SystemWakeEnabled,0x00010001,1
    A google search there will yield some context.  Unfortunately, after placing it in 2 different locations, I still haven't found success.

    2)
    So in the mean time, I returned my focus to linux and attempting to get the Microchip CDC USB stack to wake a linux box up.  After getting a stable install, and the "suspend" functionality working (that is, not waking immediately), I am farther along, but still haven't been able to wake up the box.

    Setup on linux:
    a) making sure the "/proc/acpi/wakeup" device has "enabled" for USB devices
    b) making sure that "lsusb -v" reports that the device supports "Remote Wakeup"
    c) making sure that "sys/bus/usb/devices/..../power/wakeup" for the device is set to enabled.

    Things that work:
    a) USBGetRemoteWakeupStatus() correctly reports "false" when the machine is awake, and correctly reports "true" when the machine is in standby
    b) a USB mouse will bring the computer back out of sleep


    The problem and remaining question:
    I have been unable to get the device to bring the linux computer out of sleep.  I have tried the USBCBSendResume() routine, and have also tried simply setting "USBResumeControl= 1;" for 10 ms.  Neither has worked for me in this situation.  Is there something more complex here and I am missing something, or once again, am I bumping up on generic OS driver issues?


    -stephanick
    #5
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/24 00:09:21 (permalink)
    0

    1) 
    I got a tip that the windows inf file can have an effect on remote wakeup, and that a setting in it could solve the problem.  Specifically, the registry entry: 
    HKR,,SystemWakeEnabled,0x00010001,1

    SystemWakeEnabled registry value is available for KMDF/UMDF drivers (include WinUSB). But it doesn't work for WDM drivers.

    I disassembled usbser.sys (WinXP SP3, Win7 x86 and its KB925681 hotfix) using IDA Pro. They access just to these registry values, 
    PortName, Identifier, SERIALCOMM, DosDevices
    SystemWakeEnabled access is not found on these usbser.sys.

    I also examined the source code of serenum.sys on WDK (C:\WINDDK\7600.16385.1\src\serial\serenum). I don't see any code which support remote wakeup, described in this MSDN topic.
    http://msdn.microsoft.com...y/ff563907(VS.85).aspx

    With these investigations, I believe Windows don't support remote wakeup for CDC.


    As a workaround, additional HID interface to CDC (ie. CDC + HID composite device) will work for remote wakeup.


    Tsuneo

    post edited by chinzei - 2011/01/24 00:19:56
    #6
    rainshadowtech
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2009/03/11 20:32:16
    • Location: 0
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/30 13:56:27 (permalink)
    0
    Thank you much for the investigation into windows behavior, I probably wouldn't have got that far.  I did take your advice and create a CDC + HID mouse composite device.

    Made some significant progress, though I am still left thinking "what the f**?".

    a)
    On the linux side, I did finally figure out how to bring the host out of sleep.  The CDC example code did not set the UCON SUSPND bit when it was told to go to sleep.  Once that bit was set on sleep, and cleared just before the USBResumeControl signal is set for 10ms, everything is copacetic.  The composite device works in linux for both interfaces (the serial port and mouse movement), and wakes the computer up on command.


    b)
    On windows, though, I now can instantly get the dreaded "blue screen of death" when plugging the device into a windows7-64 bit machine.  On my older machine, (windows7-32bit upgraded from vista), the composite device works mostly fine.  That is, the serial port functionality is good, the mouse movement is good, and the device manager shows the correct devices are operating.  The trouble here, though, is that when I attempt to put this second machine to sleep, here comes the "blue screen of death" again.


    As a result, I can't operate the device on the new machine, and can't put the old machine to sleep.


    Any ideas of where start on this?  For what it is worth, here is the configuration descriptor:


    /* Device Descriptor */
    ROM USB_DEVICE_DESCRIPTOR device_dsc=
    {
        0x12,                   // Size of this descriptor in bytes
        USB_DESCRIPTOR_DEVICE,  // DEVICE descriptor type
        0x0200,                 // USB Spec Release Number in BCD format    //TODO: workaround for BSTALL erratum
        0xEF,             // Class Code, misc. w/ interface associated descriptor (IAD)
        0x02,                   // Subclass code, common class
        0x01,                   // Protocol code, 1 for IAD
        USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
        0x4D8,                  // Vendor ID
        0xFF59,                 // Product ID: RainShadow HDMI-CEC to USB
        0x0008,                 // Device release number in BCD format
        0x01,                   // Manufacturer string index
        0x02,                   // Product string index
        0x00,                   // Device serial number string index
        0x01                    // Number of possible configurations
    };




    /* Configuration 1 Descriptor */
    ROM BYTE configDescriptor1[]={
        /* Configuration Descriptor */
        0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
        USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
        100,0,                   // Total length of data for this cfg
        3,                      // Number of interfaces in this cfg, 2 for CDC, 1 for HID, 3 total
        1,                      // Index value of this configuration
        0,                      // Configuration string index
        _DEFAULT | _RWU, // Attributes, see usb_device.h
        50,                     // Max power consumption (2X mA)

    /* Interface Association Descriptor */ 
    8, //sizeof(USB_IAD_DSC), // Size of this descriptor in byte 
    0x0b, //DSC_IAD, // Interface assocication descriptor type 
    0, // The first associated interface 
    2, // Number of contiguous associated interface 
    COMM_INTF, // bInterfaceClass of the first interface 
    ABSTRACT_CONTROL_MODEL, // bInterfaceSubclass of the first interface 
    V25TER, // bInterfaceProtocol of the first interface 
    0, // Interface string index 


       /* Interface Descriptor */
        9,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
        USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
        CDC_COMM_INTF_ID,       // Interface Number
        0,                      // Alternate Setting Number
        1,                      // Number of endpoints in this intf
        COMM_INTF,              // Class code
        ABSTRACT_CONTROL_MODEL, // Subclass code
        V25TER,                 // Protocol code
        0,                      // Interface string index


        /* CDC Class-Specific Descriptors */
        sizeof(USB_CDC_HEADER_FN_DSC),
        CS_INTERFACE,
        DSC_FN_HEADER,
        0x10,0x01,


        sizeof(USB_CDC_ACM_FN_DSC),
        CS_INTERFACE,
        DSC_FN_ACM,
        USB_CDC_ACM_FN_DSC_VAL,


        sizeof(USB_CDC_UNION_FN_DSC),
        CS_INTERFACE,
        DSC_FN_UNION,
        CDC_COMM_INTF_ID,
        CDC_DATA_INTF_ID,


        sizeof(USB_CDC_CALL_MGT_FN_DSC),
        CS_INTERFACE,
        DSC_FN_CALL_MGT,
        0x00,
        CDC_DATA_INTF_ID,


        /* Endpoint Descriptor */
        //sizeof(USB_EP_DSC),DSC_EP,_EP02_IN,_INT,CDC_INT_EP_SIZE,0x02,
        0x07,/*sizeof(USB_EP_DSC)*/
        USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
        _EP02_IN,            //EndpointAddress
        _INTERRUPT,                       //Attributes
        0x08,0x00,                  //size
        0x02,                       //Interval


        /* Interface Descriptor */
        9,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
        USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
        CDC_DATA_INTF_ID,       // Interface Number
        0,                      // Alternate Setting Number
        2,                      // Number of endpoints in this intf
        DATA_INTF,              // Class code
        0,                      // Subclass code
        NO_PROTOCOL,            // Protocol code
        0,                      // Interface string index
        
        /* Endpoint Descriptor */
        //sizeof(USB_EP_DSC),DSC_EP,_EP03_OUT,_BULK,CDC_BULK_OUT_EP_SIZE,0x00,
        0x07,/*sizeof(USB_EP_DSC)*/
        USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
        _EP03_OUT,            //EndpointAddress
        _BULK,                       //Attributes
        0x40,0x00,                  //size
        0x00,                       //Interval


        /* Endpoint Descriptor */
        //sizeof(USB_EP_DSC),DSC_EP,_EP03_IN,_BULK,CDC_BULK_IN_EP_SIZE,0x00
        0x07,/*sizeof(USB_EP_DSC)*/
        USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
        _EP03_IN,            //EndpointAddress
        _BULK,                       //Attributes
        0x40,0x00,                  //size
        0x00,                       //Interval


        /* Interface Descriptor */
        0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
        USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
        HID_INTF_ID,            // Interface Number
        0,                      // Alternate Setting Number
        1,                      // Number of endpoints in this intf
        HID_INTF,               // Class code
        BOOT_INTF_SUBCLASS,     // Subclass code
        HID_PROTOCOL_MOUSE,     // Protocol code
        0,                      // Interface string index


        /* HID Class-Specific Descriptor */
        0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes RRoj hack
        DSC_HID,                // HID descriptor type
        DESC_CONFIG_WORD(0x0111),                 // HID Spec Release Number in BCD format (1.11)
        0x00,                   // Country Code (0x00 for Not supported)
        HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
        DSC_RPT,                // Report descriptor type
        DESC_CONFIG_WORD(50),   //sizeof(hid_rpt01),      // Size of the report descriptor
        
        /* Endpoint Descriptor */
        0x07,/*sizeof(USB_EP_DSC)*/
        USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
        HID_EP | _EP_IN,            //EndpointAddress
        _INTERRUPT,                       //Attributes
        DESC_CONFIG_WORD(3),                  //size
        0x01                        //Interval


    };



    #7
    rainshadowtech
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2009/03/11 20:32:16
    • Location: 0
    • Status: offline
    Re:USBGetRemoteWakeupStatus(), linux as expected, windows 7 still a puzzle... 2011/01/30 21:23:10 (permalink)
    0
    Finally got something to work reasonably after banging my head trying to characterize windows.  For posterity, in the context of the example "USB Device - CDC - Basic Demo" for a PIC18F87J50, here is a summary of my findings:

    1)
    Windows will not "arm" a USB device for remote wakeup unless it has a "power management" tab available from the device manager.  What I mean by "arm" is that the function USBGetRemoteWakeupStatus() of the USB stack will always return FALSE, even though the "_RWU" flag is enabled in the descriptor.


    2)
    Thus, if implementing an HID like a mouse, there is no problem, windows arms the device fine.  But when implementing the CDC USB-to-serial emulator, windows does not seem capable of accomplishing this.


    3)
    All is not lost though, in the case of the CDC implementation, even though the device is not "armed", you can still wake up the host with the correct signaling.  Windows does not seem to care if the device was previously armed or not.


    4)
    But, in order to signal the host to wakeup up, you cannot simply signal the host with the RESUME bit set for 10ms.  You have to first suspend the device by setting the SUSPND bit.  Then to wake up the host, clear the SUSPND bit and then assert the RESUME bit for 10ms.  This was the trick that finally got it to work for me.  *Note* that the CDC demo software does not set or clear the SUSPND bit when it is told to suspend or wakeup.


    5)
    Apparently, windows 7 still seems to have major problems with IADs and composite devices.  I was able to blue screen windows by plugging in the composite device designed to use windows drivers (no custom drivers involved).  In the ideal world, even if the descriptor was bad, windows shouldn't blue screen.  (how long have these drivers been out there?)


    Hope this helps someone.
    -stephanick






    #8
    Jump to:
    © 2019 APG vNext Commercial Version 4.5