tmk / tmk_keyboard

Keyboard firmwares for Atmel AVR and Cortex-M
3.98k stars 1.7k forks source link

USB-USB: suspend/wake support for keyboard #769

Closed tmk closed 9 months ago

tmk commented 10 months ago

Problem

The converter does not support to suspend a keyboard. MAX3421E and keyboard keep drawing power while computer is sleeping.

TODO

tmk commented 9 months ago

MAX3421e RWUIRQ issue

Seemingly RWUIRQ is not triggered with remote wakeup from some devices. This seems to depend on remote wake implementation and singnal term(1-15ms).

RWUIRQ does not work with:

OK with:

https://electronics.stackexchange.com/questions/372236/bugs-in-maxim-chip-max3421e-used-as-usb-host

WORK AROUND

Check bus state using SAMPLEBUS and detect remote wakeup signal when bus is K state.

This does not detect remote wakeup signal every time. This can miss it and you will have to hold a key a while or press several times in that case.

        // sample bus
        regWr(rHCTL, bmSAMPLEBUS);
        while(!(regRd(rHCTL) & bmSAMPLEBUS));

        uint8_t bus_sample;
        bus_sample = regRd(rHRSL);
        bus_sample &= (bmJSTATUS | bmKSTATUS);

        if (bus_sample == bmKSTATUS) {
            // K-state means remote wakeup when suspended
        }

https://github.com/tmk/USB_Host_Shield_2.0/commit/001fe4c48acde567194ea91ac9a4a52c67d804c0

tmk commented 9 months ago

DEVICE_REMOTE_WAKEUP

To enable Remote Wakeup on a device/keyboard we need to send SET_FEATURE request using ctrlReq() :

        // SET_FEATURE(DEVICE_REMOTE_WAKEUP)                    
        rcode = pUsb->ctrlReq(bAddress,                        
                        0, // End Point: 0                                                                            
                        (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE), // bmRequestType                                                                                                                 
                        USB_REQUEST_SET_FEATURE,    // bRequest                             
                        USB_FEATURE_DEVICE_REMOTE_WAKEUP, 0,    // wValue             
                        0,  // wIndex                                                             
                        0, 0, NULL, NULL);  // wLength                   
        USBTRACE2("RWU: ", rcode); 

https://github.com/tmk/USB_Host_Shield_2.0/commit/3baa2f00263724274534d48e228b13516fb8980d

tmk commented 9 months ago

Power Saving

Even in host mode MAX3421E can enter into low-power state using PWRDOWN bit,

though document says:

This bit is designed only for peripheral mode usage, although it is accessible in host mode. The CPU should never set POWERDOWN = 1 when operating as a host.

In low-power state the chip cannot detect and handle any USB events such like remote wakeup, attach and detach. You will have to enumerate and intialize a device after putting out of low-power state.

When enabling remote wakeup we cannot put the chip into the low-power state.

https://github.com/tmk/USB_Host_Shield_2.0/commit/d6d26f92a7fad28d570ce22de2bc6b2fb42943b0

https://github.com/tmk/tmk_keyboard/commit/09664638f87949db7c8f9f2deb1c7ca2879132ae

tmk commented 9 months ago

Current the converter draws while in "configured"

around 22.3mA in active state

Current the converter draws while in "suspended"

when Remote Wakeup is enabled

The converter draws around 7.8mA(without keyboard) or 8.2mA(with keyboard).

MAX3421 is powered up.

when Remote Wakeup is disabled

The converter draws around 0.1mA.

MAX3421 is powered down.