dlkj/usbd-human-interface-device

Support for use with Monotonic/in RTIC application

Closed this issue · 8 comments

0xa10 commented

Hi, I'm trying to use this library instead of usbd-hid which does not seem to offer composite device support.
I'd like to use both Consumer reports (which I have already implemented and work fine) and NKRO/BOOT keyboard codes - however for using either one of those I'm expected to provide a clock object which implements the embedded_time Clock trait.

Given the functionality offered by it - this seems to preclude me from using this library while using a Monotonic clock - which is essential for RTIC.
Other than implementing a Clock-y timer over the Monotonic primitives, is there any other way I'd be able to send Keyboard reports? I only need to send volume up/down (non-Consumer) reports.

Thanks

dlkj commented

To support HID idle, the ManagedInterface needs the ability to set timers. To avoid requiring the use of interrupts and a dedicated timer it uses the embedded_time::clock::Clock trait to abstract this.

You could implement the Clock for your Monotonic or you could use a RawInterface. This requires the user to meet any time requirements to implement HID idle, if required. Generally most modern OSs immediately disable HID idle after device configuration.

Something like:

    let mut keyboard = UsbHidClassBuilder::new()
        .add_interface(
            RawInterfaceBuilder::new(NKRO_BOOT_KEYBOARD_REPORT_DESCRIPTOR)
                .description("Custom Keyboard")
                .idle_default(Milliseconds(500))
                .unwrap()
                .in_endpoint(UsbPacketSize::Bytes8, Milliseconds(10))
                .unwrap()
                .with_out_endpoint(UsbPacketSize::Bytes8, Milliseconds(100))
                .unwrap()
                .build(),
        )
        .build(&usb_bus);

See https://github.com/dlkj/usbd-human-interface-device/blob/main/examples/src/bin/keyboard_custom.rs for a more fully worked out example where the end user code implements the HID idle functionality rather than delegating it to the library.

dlkj commented

Native library support for use with RTIC would be useful for many people so it is definitely something I'd consider implementing or adding to the library.

dlkj commented

Similarly support for fugit would also be desirable as this seems to be getting more traction than embedded-time.

On top of that providing a more ergonomic way of opting out of managed idle would be nice.

0xa10 commented

Thanks for information and advice! I'll give the RawInterface approach a try.
At the moment I'm not quite sure I understand the host/device interactions well enough, but I'll look into it and will be happy to contribute to any RTIC support efforts.

0xa10 commented

I've been trying to wrap my head around the HID idle functionality -
If I understand correctly - the idea is that once the idle duration has elapsed, but the key state has not changed, the device will start repeating the last sent report.
Im not quite sure I understand the de-facto host/device interaction regarding this setting - does the host request changes to this value by default?

My use case is a simple volume control - specifically one driven by a rotary encoder - so as far as I can tell there shouldn't be any need for repeating reports - each turn triggers an an interrupt which in turns triggers the report being written.
In a sense the current key state cannot be "held" for any duration.

In that case - can I get away with omitting support for this altogether and just use the RawInterface as shown in your demonstration, simply without the last_keys logic?

Thanks again.

dlkj commented

You can omit all the HID idle functionality if you like. Idle support is optional for most usb HID implementations except the boot keyboard.

The library implements this to be fully compliant with the spec, but individual devices may not need to support it. Almost all modern hosts don't rely on idle. Some computer bios keyboard drivers may require it.

dlkj commented

@0xa10 - I've made changes to how the library implements the HID idle functionality. I no longer requires you to implement a Clock. Take a look at the latest version (0.3.1). I'm also working on an example using RTIC on this branch: https://github.com/dlkj/usbd-human-interface-device/tree/rtic