evdev_rs

Struct UInputDevice

Source
pub struct UInputDevice { /* private fields */ }
Expand description

Opaque struct representing an evdev uinput device

Implementations§

Source§

impl UInputDevice

Source

pub fn create_from_device<T: DeviceWrapper>(device: &T) -> Result<UInputDevice>

Create a uinput device based on the given libevdev device.

The uinput device will be an exact copy of the libevdev device, minus the bits that uinput doesn’t allow to be set.

Examples found in repository?
examples/vmouse.rs (line 58)
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
fn main() -> Result<(), std::io::Error> {
    // Parse command line arguments
    let mut args = std::env::args();

    if args.len() != 2 {
        let n = args.nth(0).unwrap();
        println!("Usage: `{} DEVICE`, eg. `{} /dev/input/event13`", n, n);
        std::process::exit(1);
    }

    let device = &args.nth(1).unwrap();

    // Connect to real keyboard
    let f = File::open(device)?;
    let d = Device::new_from_file(f)?;

    if let Some(n) = d.name() {
        println!(
            "Connected to device: '{}' ({:04x}:{:04x})",
            n,
            d.vendor_id(),
            d.product_id()
        );
    }

    // Create virtual device
    let u = UninitDevice::new().unwrap();

    // Setup device
    // per: https://01.org/linuxgraphics/gfx-docs/drm/input/uinput.html#mouse-movements

    u.set_name("Virtual Mouse");
    u.set_bustype(BusType::BUS_USB as u16);
    u.set_vendor_id(0xabcd);
    u.set_product_id(0xefef);

    // Note mouse keys have to be enabled for this to be detected
    // as a usable device, see: https://stackoverflow.com/a/64559658/6074942
    u.enable_event_type(&EventType::EV_KEY)?;
    u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_LEFT), None)?;
    u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_RIGHT), None)?;

    u.enable_event_type(&EventType::EV_REL)?;
    u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_X), None)?;
    u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_Y), None)?;

    u.enable_event_code(&EventCode::EV_SYN(EV_SYN::SYN_REPORT), None)?;

    // Attempt to create UInputDevice from UninitDevice
    let v = UInputDevice::create_from_device(&u)?;

    loop {
        // Fetch keyboard events
        let (_status, event) = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING)?;

        // Map these to mouse events
        println!("Event: {:?}", event);

        // Map direction keys to mouse events
        let e = match event.event_code {
            EventCode::EV_KEY(EV_KEY::KEY_RIGHT) => Some((EV_REL::REL_X, MOUSE_STEP_X)),
            EventCode::EV_KEY(EV_KEY::KEY_LEFT) => Some((EV_REL::REL_X, -MOUSE_STEP_X)),
            EventCode::EV_KEY(EV_KEY::KEY_UP) => Some((EV_REL::REL_Y, -MOUSE_STEP_Y)),
            EventCode::EV_KEY(EV_KEY::KEY_DOWN) => Some((EV_REL::REL_Y, MOUSE_STEP_Y)),
            _ => None,
        };

        // Write mapped event
        if let Some((e, n)) = e {
            v.write_event(&InputEvent {
                time: event.time,
                event_code: EventCode::EV_REL(e),
                value: n,
            })?;

            v.write_event(&InputEvent {
                time: event.time,
                event_code: EventCode::EV_SYN(EV_SYN::SYN_REPORT),
                value: 0,
            })?;
        }
    }
}
Source

pub fn devnode(&self) -> Option<&str>

Return the device node representing this uinput device.

This relies on libevdev_uinput_get_syspath() to provide a valid syspath.

Source

pub fn syspath(&self) -> Option<&str>

Return the syspath representing this uinput device.

If the UI_GET_SYSNAME ioctl not available, libevdev makes an educated guess. The UI_GET_SYSNAME ioctl is available since Linux 3.15.

The syspath returned is the one of the input node itself (e.g. /sys/devices/virtual/input/input123), not the syspath of the device node returned with libevdev_uinput_get_devnode().

Source

pub fn as_fd(&self) -> Option<RawFd>

Return the file descriptor used to create this uinput device.

This is the fd pointing to /dev/uinput. This file descriptor may be used to write events that are emitted by the uinput device. Closing this file descriptor will destroy the uinput device.

Source

pub fn fd(&self) -> Option<RawFd>

👎Deprecated since 0.5.0: Prefer as_fd. Some function names were changed so they more closely match their type signature. See issue 42 for discussion https://github.com/ndesh26/evdev-rs/issues/42
Source

pub fn write_event(&self, event: &InputEvent) -> Result<()>

Post an event through the uinput device.

It is the caller’s responsibility that any event sequence is terminated with an EV_SYN/SYN_REPORT/0 event. Otherwise, listeners on the device node will not see the events until the next EV_SYN event is posted.

Examples found in repository?
examples/vmouse.rs (lines 78-82)
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
fn main() -> Result<(), std::io::Error> {
    // Parse command line arguments
    let mut args = std::env::args();

    if args.len() != 2 {
        let n = args.nth(0).unwrap();
        println!("Usage: `{} DEVICE`, eg. `{} /dev/input/event13`", n, n);
        std::process::exit(1);
    }

    let device = &args.nth(1).unwrap();

    // Connect to real keyboard
    let f = File::open(device)?;
    let d = Device::new_from_file(f)?;

    if let Some(n) = d.name() {
        println!(
            "Connected to device: '{}' ({:04x}:{:04x})",
            n,
            d.vendor_id(),
            d.product_id()
        );
    }

    // Create virtual device
    let u = UninitDevice::new().unwrap();

    // Setup device
    // per: https://01.org/linuxgraphics/gfx-docs/drm/input/uinput.html#mouse-movements

    u.set_name("Virtual Mouse");
    u.set_bustype(BusType::BUS_USB as u16);
    u.set_vendor_id(0xabcd);
    u.set_product_id(0xefef);

    // Note mouse keys have to be enabled for this to be detected
    // as a usable device, see: https://stackoverflow.com/a/64559658/6074942
    u.enable_event_type(&EventType::EV_KEY)?;
    u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_LEFT), None)?;
    u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_RIGHT), None)?;

    u.enable_event_type(&EventType::EV_REL)?;
    u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_X), None)?;
    u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_Y), None)?;

    u.enable_event_code(&EventCode::EV_SYN(EV_SYN::SYN_REPORT), None)?;

    // Attempt to create UInputDevice from UninitDevice
    let v = UInputDevice::create_from_device(&u)?;

    loop {
        // Fetch keyboard events
        let (_status, event) = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING)?;

        // Map these to mouse events
        println!("Event: {:?}", event);

        // Map direction keys to mouse events
        let e = match event.event_code {
            EventCode::EV_KEY(EV_KEY::KEY_RIGHT) => Some((EV_REL::REL_X, MOUSE_STEP_X)),
            EventCode::EV_KEY(EV_KEY::KEY_LEFT) => Some((EV_REL::REL_X, -MOUSE_STEP_X)),
            EventCode::EV_KEY(EV_KEY::KEY_UP) => Some((EV_REL::REL_Y, -MOUSE_STEP_Y)),
            EventCode::EV_KEY(EV_KEY::KEY_DOWN) => Some((EV_REL::REL_Y, MOUSE_STEP_Y)),
            _ => None,
        };

        // Write mapped event
        if let Some((e, n)) = e {
            v.write_event(&InputEvent {
                time: event.time,
                event_code: EventCode::EV_REL(e),
                value: n,
            })?;

            v.write_event(&InputEvent {
                time: event.time,
                event_code: EventCode::EV_SYN(EV_SYN::SYN_REPORT),
                value: 0,
            })?;
        }
    }
}

Trait Implementations§

Source§

impl Debug for UInputDevice

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for UInputDevice

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for UInputDevice

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.