Struct kiibohd_usb::HidInterface
source · pub struct HidInterface<'a, B: UsbBus, const KBD_SIZE: usize, const KBD_LED_SIZE: usize, const MOUSE_SIZE: usize, const CTRL_SIZE: usize> { /* private fields */ }Expand description
USB HID Combination Interface
Handles creation and management of multiple USB HID interfaces through SPSC queues. Maintains state for you so you only need to send state changes and poll events.
Typical Usage
- Queue up changes using SPSC queues
- Call push to send the current states of all the queues (queues are not processed until push() is called)
HID-IO
- Queue up changes, or receive changes using hidio_rx and hidio_tx spsc queues
- Call poll to process queues in both directions (or push, which will call poll for you) Will attempt to push and pull as many packets as possible in case the USB device supports larger buffers (e.g. double buffering)
Example Usage (atsam4s)
use heapless::spsc::Queue;
use usbd_hid::hid_class::{HidCountryCode, HidProtocolMode, ProtocolModeConfig};
// These define the maximum pending items in each queue
const KBD_QUEUE_SIZE: usize = 10; // This would limit NKRO mode to 10KRO
const KBD_LED_QUEUE_SIZE: usize = 3;
const MOUSE_QUEUE_SIZE: usize = 5;
const CTRL_QUEUE_SIZE: usize = 2;
type HidInterface =
kiibohd_usb::HidInterface<'static, UdpBus, KBD_QUEUE_SIZE, MOUSE_QUEUE_SIZE, CTRL_QUEUE_SIZE>;
pub struct HidioInterface<const H: usize> {}
impl<const H: usize> HidioInterface<H> {
fn new() -> Self {
Self {}
}
}
impl<const H: usize> KiibohdCommandInterface<H> for HidioInterface<H> {
fn h0001_device_name(&self) -> Option<&str> {
Some("Input Club Keystone - TKL")
}
fn h0001_firmware_name(&self) -> Option<&str> {
Some("kiibohd-firmware")
}
}
// Setup the queues used to generate the input reports (ctrl, keyboard and mouse)
let ctrl_queue: Queue<kiibohd_usb::CtrlState, CTRL_QUEUE_SIZE> = Queue::new();
let kbd_queue: Queue<kiibohd_usb::KeyState, KBD_QUEUE_SIZE> = Queue::new();
let kbd_led_queue: Queue<kiibohd_usb::LedState, KBD_LED_QUEUE_SIZE> = Queue::new();
let mouse_queue: Queue<kiibohd_usb::MouseState, MOUSE_QUEUE_SIZE> = Queue::new();
let (kbd_producer, kbd_consumer) = kbd_queue.split();
let (mouse_producer, mouse_consumer) = mouse_queue.split();
let (ctrl_producer, ctrl_consumer) = ctrl_queue.split();
// Setup the interface
// NOTE: Ignoring usb_bus setup in this example, use a compliant usb-device UsbBus interface
let usb_hid = HidInterface::new(
usb_bus,
HidCountryCode::NotSupported,
kbd_consumer,
kbd_led_producer,
mouse_consumer,
ctrl_consumer,
);
// Basic CommandInterface
let hidio_intf = CommandInterface::<
HidioInterface<MESSAGE_LEN>,
TX_BUF,
RX_BUF,
BUF_CHUNK,
MESSAGE_LEN,
SERIALIZATION_LEN,
ID_LEN,
>::new(
&[
HidIoCommandId::SupportedIds,
HidIoCommandId::GetInfo,
HidIoCommandId::TestPacket,
],
HidioInterface::<MESSAGE_LEN>::new(),
)
.unwrap();
// To push keyboard key report, first push to the queue, then process all queues
kbd_producer.enqueue(kiibohd_usb::KeyState::Press(0x04)); // Press the A key
usb_hid.push();
// To retrieve lock leds (and enqueue events)
usb_hid.pull();
// In the USB interrupt (or similar), usb_hid will also need to be handled (Ctrl EP requests)
fn usb_irq() {
let usb_dev = some_global_mechanism.usb_dev;
let usb_hid = some_global_mechanism.usb_hid;
let hidio_intf = some_global_mechanism.hidio_intf;
if usb_dev.poll(&mut usb_hid.interfaces()) {
// poll is only available with the hidio feature
usb_hid.poll(hidio_intf);
}
}Implementations§
source§impl<B: UsbBus, const KBD_SIZE: usize, const KBD_LED_SIZE: usize, const MOUSE_SIZE: usize, const CTRL_SIZE: usize> HidInterface<'_, B, KBD_SIZE, KBD_LED_SIZE, MOUSE_SIZE, CTRL_SIZE>
impl<B: UsbBus, const KBD_SIZE: usize, const KBD_LED_SIZE: usize, const MOUSE_SIZE: usize, const CTRL_SIZE: usize> HidInterface<'_, B, KBD_SIZE, KBD_LED_SIZE, MOUSE_SIZE, CTRL_SIZE>
pub fn new<'a>( alloc: &'a UsbBusAllocator<B>, locale: HidCountryCode, kbd_consumer: Consumer<'a, KeyState, KBD_SIZE>, kbd_led_producer: Producer<'a, LedState, KBD_LED_SIZE>, mouse_consumer: Consumer<'a, MouseState, MOUSE_SIZE>, ctrl_consumer: Consumer<'a, CtrlState, CTRL_SIZE> ) -> HidInterface<'a, B, KBD_SIZE, KBD_LED_SIZE, MOUSE_SIZE, CTRL_SIZE>
sourcepub fn set_kbd_protocol_mode(
&mut self,
mode: HidProtocolMode,
config: ProtocolModeConfig
)
pub fn set_kbd_protocol_mode( &mut self, mode: HidProtocolMode, config: ProtocolModeConfig )
Dynamically update the keyboard protocol mode (and behavior) Used to force NKRO or 6KRO regardless of what the host configures
sourcepub fn get_kbd_protocol_mode(&self) -> HidProtocolMode
pub fn get_kbd_protocol_mode(&self) -> HidProtocolMode
Retrieves the current protocol mode Uses the 6kro keyboard (both HID Classes should return the same value)
sourcepub fn interfaces(&mut self) -> [&mut dyn UsbClass<B>; 5]
pub fn interfaces(&mut self) -> [&mut dyn UsbClass<B>; 5]
Used to pass all of the interfaces to usb_dev.poll()
sourcepub fn update(&mut self) -> bool
pub fn update(&mut self) -> bool
Update buffers to be ready to push over USB This is useful for remote wakeup where we only want to send a remote wakeup if an event has occurred. But before sending the data to the USB buffer registers.
Returns true if any descriptor was updated
sourcepub fn push(&mut self) -> Result<(), UsbError>
pub fn push(&mut self) -> Result<(), UsbError>
Processes each of the spsc queues and pushes data over USB This is primarily for keyboard, mouse and ctrl interfaces. HID-IO is handled with poll()
This function automatically handles USB Resume if required.
NOTE: You must call update() first before calling push().
Returns possibly returns UsbError::WouldBlock in which case the USB buffer is full and you should call push before queuing up more keypresses. Normally it’s safe to add more events; however, it’s possible you may lose an event (very slim chance).
sourcepub fn pull(&mut self)
pub fn pull(&mut self)
Query HID lock LED state The state used depends on which protocol mode is selected (there are different lock LEDs for the 6KRO/Boot and NKRO keyboard descriptors.
sourcepub fn pull_hidio<KINTF: KiibohdCommandInterface<H>, const TX: usize, const RX: usize, const N: usize, const H: usize, const S: usize, const ID: usize>(
&mut self,
interface: &mut CommandInterface<KINTF, TX, RX, N, H, S, ID>
)
pub fn pull_hidio<KINTF: KiibohdCommandInterface<H>, const TX: usize, const RX: usize, const N: usize, const H: usize, const S: usize, const ID: usize>( &mut self, interface: &mut CommandInterface<KINTF, TX, RX, N, H, S, ID> )
Pull the HID-IO interface (RX)
sourcepub fn push_hidio<KINTF: KiibohdCommandInterface<H>, const TX: usize, const RX: usize, const N: usize, const H: usize, const S: usize, const ID: usize>(
&mut self,
interface: &mut CommandInterface<KINTF, TX, RX, N, H, S, ID>
)
pub fn push_hidio<KINTF: KiibohdCommandInterface<H>, const TX: usize, const RX: usize, const N: usize, const H: usize, const S: usize, const ID: usize>( &mut self, interface: &mut CommandInterface<KINTF, TX, RX, N, H, S, ID> )
Push the HID-IO interface (TX)