#usb-hid #linux #gadget #hid #input #tokio #usb

tokio-hidg

Linux USB HID Gadget emulation for tokio async runtime

3 unstable releases

0.2.0 May 11, 2024
0.1.1 Mar 2, 2023
0.1.0 Oct 2, 2022

#655 in Unix APIs

Download history 21/week @ 2024-02-26 13/week @ 2024-03-11 37/week @ 2024-04-01 154/week @ 2024-05-06 20/week @ 2024-05-13 9/week @ 2024-05-20 1/week @ 2024-05-27

184 downloads per month

MIT license

80KB
1.5K SLoC

HID Gadget Emulation in Rust

github crate docs MIT CI

Rust crate for interfacing with Linux HID Gadget devices (/dev/hidgX). This crate supports tokio async runtime.

Since all functionality is dependent on Linux function calls, this crate only compiles for Linux systems.

Crates

  • hidg-core - core abstractions and low level interface (not for end users)
  • hidg - std interface which supports synchronous operation only
  • tokio-hidg - async interface for tokio runtime
  • async-hidg - async interface for other runtimes

Features

  • fromstr - implements core::str::FromStr implementation for some types
  • display - implements std::fmt::Display implementation for some types
  • phf - use phf in core::str::FromStr trait implementations
  • serde - enables serde support for some types
  • keyboard - enables keyboard class support
  • mouse - enables mouse class support

Usage examples

Keyboard input simulation:

use tokio_hidg::{Class, Device, Keyboard, Key, Led, StateChange};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let mut device = Device::<Keyboard>::open(0).await?; // open device

    // Create input report
    let mut input = Keyboard.input();

    // Press left ctrl modifier
    input.press_key(Key::LeftCtrl);

    // Press key 'A'
    input.press_key(Key::A);

    // Print pressed keys
    println!("Keys: {:?}", input.pressed().collect::<Vec<Key>>());

    // Send input report
    device.input(&input).await?;

    // Release left ctrl modifier
    input.release_key(Key::LeftCtrl);

    // Release key 'A'
    input.release_key(Key::A);

    // Send input report
    device.input(&input).await?;

    // Create output report
    let mut output = Keyboard.output();

    // Receive output report
    device.output(&mut output).await?;

    // Print lit LEDs
    println!("LEDs: {:?}", output.lit().collect::<Vec<Led>>());

    Ok(())
}

Mouse input simulation:

use tokio_hidg::{Button, Class, Device, Mouse, StateChange, ValueChange};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let mut device = Device::<Mouse>::open("hidg0").await?; // open device

    // Create input report
    let mut input = Mouse.input();

    // Press primary button
    input.press_button(Button::Primary);

    // Set pointer coordinates
    input.change_pointer((150, 50), false);

    // Send input report
    device.input(&input).await?;

    // Move pointer relatively
    input.change_pointer((70, -30), true);

    // Print pressed buttons
    println!("Buttons: {:?}", input.pressed().collect::<Vec<Button>>());

    // Release primary button
    input.release_button(Button::Primary);

    // Send input report
    device.input(&input).await?;

    Ok(())
}

Dependencies

~3–15MB
~120K SLoC