evdev_rs

Struct UninitDevice

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

Opaque struct representing an evdev device with no backing file

Implementations§

Source§

impl UninitDevice

Source

pub fn new() -> Option<UninitDevice>

Initialize a new libevdev device.

Generally you should use Device::new_from_file instead of this method This function only initializes the struct to sane default values. To actually hook up the device to a kernel device, use set_file.

Examples found in repository?
examples/evtest.rs (line 125)
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
fn main() {
    let mut args = std::env::args();

    if args.len() != 2 {
        usage();
        std::process::exit(1);
    }

    let path = &args.nth(1).unwrap();
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .custom_flags(libc::O_NONBLOCK)
        .open(path)
        .unwrap();
    let mut buffer = Vec::new();
    let result = file.read_to_end(&mut buffer);
    if result.is_ok() || result.unwrap_err().kind() != ErrorKind::WouldBlock {
        println!("Failed to drain pending events from device file");
    }

    let u_d = UninitDevice::new().unwrap();
    let d = u_d.set_file(file).unwrap();

    println!(
        "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}",
        d.bustype(),
        d.vendor_id(),
        d.product_id()
    );
    println!("Evdev version: {:x}", d.driver_version());
    println!("Input device name: \"{}\"", d.name().unwrap_or(""));
    println!("Phys location: {}", d.phys().unwrap_or(""));
    println!("Uniq identifier: {}", d.uniq().unwrap_or(""));

    print_bits(&d);
    print_props(&d);

    let mut a: io::Result<(ReadStatus, InputEvent)>;
    loop {
        a = d.next_event(ReadFlag::NORMAL);
        if a.is_ok() {
            let mut result = a.ok().unwrap();
            match result.0 {
                ReadStatus::Sync => {
                    println!("::::::::::::::::::::: dropped ::::::::::::::::::::::");
                    while result.0 == ReadStatus::Sync {
                        print_sync_dropped_event(&result.1);
                        a = d.next_event(ReadFlag::SYNC);
                        if a.is_ok() {
                            result = a.ok().unwrap();
                        } else {
                            break;
                        }
                    }
                    println!("::::::::::::::::::::: re-synced ::::::::::::::::::::");
                }
                ReadStatus::Success => print_event(&result.1),
            }
        } else {
            let err = a.err().unwrap();
            match err.raw_os_error() {
                Some(libc::EAGAIN) => continue,
                _ => {
                    println!("{}", err);
                    break;
                }
            }
        }
    }
}
More examples
Hide additional examples
examples/vmouse.rs (line 35)
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 set_file(self, file: File) -> Result<Device>

Set the file for this struct and initialize internal data.

If the device changed and you need to re-read a device, use Device::new_from_file method. If you need to change the file after closing and re-opening the same device, use change_file.

Examples found in repository?
examples/evtest.rs (line 126)
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
fn main() {
    let mut args = std::env::args();

    if args.len() != 2 {
        usage();
        std::process::exit(1);
    }

    let path = &args.nth(1).unwrap();
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .custom_flags(libc::O_NONBLOCK)
        .open(path)
        .unwrap();
    let mut buffer = Vec::new();
    let result = file.read_to_end(&mut buffer);
    if result.is_ok() || result.unwrap_err().kind() != ErrorKind::WouldBlock {
        println!("Failed to drain pending events from device file");
    }

    let u_d = UninitDevice::new().unwrap();
    let d = u_d.set_file(file).unwrap();

    println!(
        "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}",
        d.bustype(),
        d.vendor_id(),
        d.product_id()
    );
    println!("Evdev version: {:x}", d.driver_version());
    println!("Input device name: \"{}\"", d.name().unwrap_or(""));
    println!("Phys location: {}", d.phys().unwrap_or(""));
    println!("Uniq identifier: {}", d.uniq().unwrap_or(""));

    print_bits(&d);
    print_props(&d);

    let mut a: io::Result<(ReadStatus, InputEvent)>;
    loop {
        a = d.next_event(ReadFlag::NORMAL);
        if a.is_ok() {
            let mut result = a.ok().unwrap();
            match result.0 {
                ReadStatus::Sync => {
                    println!("::::::::::::::::::::: dropped ::::::::::::::::::::::");
                    while result.0 == ReadStatus::Sync {
                        print_sync_dropped_event(&result.1);
                        a = d.next_event(ReadFlag::SYNC);
                        if a.is_ok() {
                            result = a.ok().unwrap();
                        } else {
                            break;
                        }
                    }
                    println!("::::::::::::::::::::: re-synced ::::::::::::::::::::");
                }
                ReadStatus::Success => print_event(&result.1),
            }
        } else {
            let err = a.err().unwrap();
            match err.raw_os_error() {
                Some(libc::EAGAIN) => continue,
                _ => {
                    println!("{}", err);
                    break;
                }
            }
        }
    }
}
Source

pub fn set_fd(self, file: File) -> Result<Device>

👎Deprecated since 0.5.0: Prefer set_file. 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

Trait Implementations§

Source§

impl Debug for UninitDevice

Source§

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

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

impl DeviceWrapper for UninitDevice

Source§

fn raw(&self) -> *mut libevdev

Source§

fn enable<E: Enable>(&self, e: E) -> Result<()>

Forcibly enable an EventType/InputProp on this device, even if the underlying device does not support it. While this cannot make the device actually report such events, it will now return true for has(). Read more
Source§

fn enable_property(&self, prop: &InputProp) -> Result<()>

Enables this property, a call to set_file will overwrite any previously set values Read more
Source§

fn enable_event_type(&self, ev_type: &EventType) -> Result<()>

Forcibly enable an event type on this device, even if the underlying device does not support it. While this cannot make the device actually report such events, it will now return true for libevdev_has_event_type(). Read more
Source§

fn enable_event_code( &self, ev_code: &EventCode, data: Option<EnableCodeData>, ) -> Result<()>

Forcibly enable an event type on this device, even if the underlying device does not support it. While this cannot make the device actually report such events, it will now return true for libevdev_has_event_code(). Read more
Source§

fn disable<E: Enable>(&self, d: E) -> Result<()>

Forcibly disable an EventType/EventCode on this device, even if the underlying device provides it. This effectively mutes the respective set of events. has() will return false for this EventType/EventCode Read more
Source§

fn disable_event_type(&self, ev_type: &EventType) -> Result<()>

Forcibly disable an event type on this device, even if the underlying device provides it. This effectively mutes the respective set of events. libevdev will filter any events matching this type and none will reach the caller. libevdev_has_event_type() will return false for this type. Read more
Source§

fn disable_event_code(&self, code: &EventCode) -> Result<()>

Forcibly disable an event code on this device, even if the underlying device provides it. This effectively mutes the respective set of events. libevdev will filter any events matching this type and code and none will reach the caller. has_event_code will return false for this code. Read more
Source§

fn has<E: Enable>(&self, e: E) -> bool

Returns true if device support the InputProp/EventType/EventCode and false otherwise
Source§

fn has_property(&self, prop: &InputProp) -> bool

Returns true if device support the property and false otherwise Read more
Source§

fn has_event_type(&self, ev_type: &EventType) -> bool

Returns true is the device support this event type and false otherwise Read more
Source§

fn has_event_code(&self, code: &EventCode) -> bool

Return true is the device support this event type and code and false otherwise Read more
Source§

fn name(&self) -> Option<&str>

Get device’s name, as set by the kernel, or overridden by a call to set_name
Source§

fn phys(&self) -> Option<&str>

Get device’s physical location, as set by the kernel, or overridden by a call to set_phys
Source§

fn uniq(&self) -> Option<&str>

Get device’s unique identifier, as set by the kernel, or overridden by a call to set_uniq
Source§

fn set_name(&self, field: &str)

Source§

fn set_phys(&self, field: &str)

Source§

fn set_uniq(&self, field: &str)

Source§

fn product_id(&self) -> u16

Source§

fn vendor_id(&self) -> u16

Source§

fn bustype(&self) -> u16

Source§

fn version(&self) -> u16

Source§

fn set_product_id(&self, field: u16)

Source§

fn set_vendor_id(&self, field: u16)

Source§

fn set_bustype(&self, field: u16)

Source§

fn set_version(&self, field: u16)

Source§

fn abs_info(&self, code: &EventCode) -> Option<AbsInfo>

Get the axis info for the given axis, as advertised by the kernel. Read more
Source§

fn set_abs_info(&self, code: &EventCode, absinfo: &AbsInfo)

Change the abs info for the given EV_ABS event code, if the code exists. Read more
Source§

fn event_value(&self, code: &EventCode) -> Option<i32>

Returns the current value of the event type. Read more
Source§

fn set_event_value(&self, code: &EventCode, val: i32) -> Result<()>

Set the value for a given event type and code. Read more
Source§

fn abs_minimum(&self, code: u32) -> Result<i32>

Source§

fn abs_maximum(&self, code: u32) -> Result<i32>

Source§

fn abs_fuzz(&self, code: u32) -> Result<i32>

Source§

fn abs_flat(&self, code: u32) -> Result<i32>

Source§

fn abs_resolution(&self, code: u32) -> Result<i32>

Source§

fn set_abs_minimum(&self, code: u32, val: i32)

Source§

fn set_abs_maximum(&self, code: u32, val: i32)

Source§

fn set_abs_fuzz(&self, code: u32, val: i32)

Source§

fn set_abs_flat(&self, code: u32, val: i32)

Source§

fn set_abs_resolution(&self, code: u32, val: i32)

Source§

fn slot_value(&self, slot: u32, code: &EventCode) -> Option<i32>

Return the current value of the code for the given slot. Read more
Source§

fn set_slot_value(&self, slot: u32, code: &EventCode, val: i32) -> Result<()>

Set the value for a given code for the given slot. Read more
Source§

fn num_slots(&self) -> Option<i32>

Get the number of slots supported by this device. Read more
Source§

fn current_slot(&self) -> Option<i32>

Get the currently active slot. Read more
Source§

impl Drop for UninitDevice

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for UninitDevice

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.