Expand description
§cruil: Charlotte’s Raw USB Input Library
(Pronounced “cru-ill” or “cruel”)
cruil is a library that uses raw USB HID under the hood to be able to distinguish between and read input from input devices that are usually combined by the operating system (keyboards, mice)
On supported operating systems, this also includes Bluetooth HID devices.
[!WARNING]
cruil is still really early in development.
The entire API may change in the future.
See “Currently broken/WIP/unimplemented” for a list of current limitations.
§Why is this useful?
Some ideas:
- Local multi-player video games that use keyboards and mice
- Simulation software that uses multiple keyboards to create large control panels
- Software to create a large emoji keyboard, à la Tom Scott, but without the bodge
- Multi-seat software that uses multiple mice to create multiple pointers on one screen
§What cruil does NOT do
- Handle keyboard layouts (as of now, this may change in the future if necessary)
- Map keys or key combinations to typed characters (out of scope)
§Currently broken/WIP/unimplemented
- Report descriptor parsing, which breaks:
- Linux, BSD, and other Unix support
- A lot of keyboards and mice
- Turns out that more advanced devices don’t allow you to get off the hook easily anymore
- Linux, BSD, and other Unix: Bluetooth
- dependency limitation, will look into solving this in the future
§Operating system quirks
Cruil uses hidapi under the hood, so it inherits a lot of the same limitations:
- Windows: everything should just work
- macOS: requires input monitoring permissions
- Linux, BSD, and other Unix: uses the libusb backend, so Bluetooth is unsupported
§Example
From examples/player_one.rs:
use cruil::keyboard::*;
use cruil::*;
fn main() -> CruilResult<()> {
let cruil = Cruil::new()?;
let mut devices: Vec<KeyboardDevice> = cruil
.open_all_with(|info| matches!(DeviceKind::from_info(info), Ok(DeviceKind::Keyboard)))
.into_iter()
.map(|device| device.keyboard())
.collect::<Option<Vec<_>>>()
.unwrap();
// The first keyboard to press a key becomes player one!
println!("Press any key to join!");
let player_one = 'player_select: loop {
for (index, device) in devices.iter_mut().enumerate() {
if let Some(report) = device.try_read()?
&& report.just_pressed.any()
{
// First key press!
break 'player_select index;
}
}
};
// Let's drop all other devices and get ownership over the player
let player_one = devices.into_iter().nth(player_one).unwrap();
// Let's start reading player one's input in the background
let player_one = ThreadedReader::start(player_one);
// Game loop...
loop {
let events: Vec<KeyboardInputState> = player_one.iter().collect::<CruilResult<_>>()?;
for event in events {
// Process game input...
if event.currently_pressed.any() {
println!("Player 1 is pressing {}", event.currently_pressed);
}
}
// Process the game...
}
}Modules§
Structs§
- Cruil
- Cruil’s main struct. Get started here!
- Owned
Readable Device Iter - A
ReadableDeviceIterthat owns theReadableDevice, obtained throughReadableDevice::owned_iter, or anIntoIterator::into_iterimplementation. - Owned
Threaded Reader Iter - A
ThreadedReaderIterthat owns theThreadedReader, obtained throughThreadedReader::into_iter. - Readable
Device Iter ReadableDeviceIterimplementsIteratorby callingtry_readin thenextfunction.- Threaded
Reader - A threaded reader that can be asynchronously polled for events.
- Threaded
Reader Iter ThreadedReaderIterimplementsIteratorby callingpoll_eventin thenextfunction.- Threaded
Reader TryIter - An iterator that takes ownership of a
ThreadedReaderand iterates over it while also catching a possible internal thread panic. - Unrecognized
Key - An error that indicates that the given key code sent by the device is unknown and could not be parsed.
Enums§
- Cruil
Error - Cruil’s all-encompassing error type.
- Device
Kind - An enum containing cruil’s built-in supported device kinds,
KeyboardandMouse. - Input
Device - An opened input device, which is either a
Keyboardor aMouse. (The two types of devices Cruil has built-in support for) - Input
State - An input state obtained by
reading anInputDevice. - Keyboard
Error - An error that indicates that something went wrong with the keyboard device, presumably a hardware fault.
- Protocol
Violation - An error that indicates that the device sent an invalid response.
Constants§
- MAX_
HID_ PACKET_ SIZE - The maximum size of a HID packet.
Traits§
- Readable
Device - A device which HID reports (aka “events” or “frames”) can be read from.
Type Aliases§
- Cruil
Result - Cruil’s
Resulttype.