1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
// Create a virtual force feedback device, just while this is running.
use evdev::{
uinput::VirtualDevice, AttributeSet, EventSummary, FFEffectCode, FFStatusCode, InputEvent,
UInputCode,
};
use std::collections::BTreeSet;
fn main() -> std::io::Result<()> {
let mut device = VirtualDevice::builder()?
.name("Fake Force Feedback")
.with_ff(&AttributeSet::from_iter([FFEffectCode::FF_RUMBLE]))?
.with_ff_effects_max(16)
.build()?;
for path in device.enumerate_dev_nodes_blocking()? {
let path = path?;
println!("Available as {}", path.display());
}
let mut ids: BTreeSet<u16> = (0..16).collect();
println!("Waiting for Ctrl-C...");
loop {
let events: Vec<InputEvent> = device.fetch_events()?.collect();
const STOPPED: i32 = FFStatusCode::FF_STATUS_STOPPED.0 as i32;
const PLAYING: i32 = FFStatusCode::FF_STATUS_PLAYING.0 as i32;
for event in events {
match event.destructure() {
EventSummary::UInput(event, UInputCode::UI_FF_UPLOAD, ..) => {
let mut event = device.process_ff_upload(event)?;
let id = ids.iter().next().copied();
match id {
Some(id) => {
ids.remove(&id);
event.set_effect_id(id as i16);
event.set_retval(0);
}
None => {
event.set_retval(-1);
}
}
println!("upload effect {:?}", event.effect());
}
EventSummary::UInput(event, UInputCode::UI_FF_ERASE, ..) => {
let event = device.process_ff_erase(event)?;
ids.insert(event.effect_id() as u16);
println!("erase effect ID = {}", event.effect_id());
}
EventSummary::ForceFeedback(.., effect_id, STOPPED) => {
println!("stopped effect ID = {}", effect_id.0);
}
EventSummary::ForceFeedback(.., effect_id, PLAYING) => {
println!("playing effect ID = {}", effect_id.0);
}
_ => {
println!("event = {:?}", event);
}
};
}
}
}
|