Hi all,
First of all, I'm new to Rust. 20-plus years ago I was an embedded software engineer in assembly and C, but after a long time in the wilderness with Java (and management), I'm using Rust to re-learn the joy of programming (rather than the joy of Powerpoint, which is more the day job.) I say that to state that it may not just be that I'm new to Rust, it may be that my programming skills are, err, rusty also.
Secondly - the last time I was asking programming questions on a forum, Usenet was still a thing. So apologies if this is the wrong place to ask for help! Do let me know if I'd be better placed elsewhere.
So, all disclaimers aside, I have something going on in Rust that is confusing the hell out of me, and I'd love to know if anyone knows where I'm going wrong...
I have a simple little project that involves reading (on Linux) a USB event stream, direct from the /dev/input
event streams. Basically, I just need to open a file (which happens to be a device special), and read the bytes in.
Opening a file and reading bytes is kind of the simplest program after Hello, World, so I've impressed myself that I've managed to make a mess of it.
The problem is this: I have written the code, and it works perfectly opening a "regular" file. But if I instead open the device, let's say /dev/input/event8
, I get an "Invalid argument" (OS error 22) when I try to read() anything. Not when the file is opened, but rather when I try to read.
Because 'endianness', I'm using the read_u32
(etc.) methods, which I gather under-the-bonnet uses read_exact
- and I can't see how Invalid argument is something that can return.
I thought maybe it was something to do with me not understanding blocking/non-blocking reads, given it's so long since I wrote real code - so I spent a lot of time looking at OpenOptions
and the like, to no avail. I also tried a little experiment - I created a FIFO special file with mkfifo
, used cat
to just pipe the device data into the fifo and then pointed my Rust program at the fifo instead of directly at the device file - and that worked absolutely fine. So it seems to be something peculiarly unique to opening device specials from Rust.
If anyone has any idea what I am doing wrong, I'd love to know!
All the best and thanks in advance,
Tim
TL;DR version:
This code would fail with an OS Error 22, on the read. On Linux. Obviously, point it at a device file that actually exists, and with permission to open the file (i.e. sudo).
fn main() {
let mut file_options = OpenOptions::new();
file_options.read(true);
file_options.write(false);
let dev_file = file_options.open("/dev/input/event8").unwrap();
// This next line will fail on a device special, but NOT on a FIFO, or
// a regular file
let anything = dev_file.read_u32::<LittleEndian>()?;
}
I am SURE there must be something incredibly obvious that I'm doing wrong - but I honestly cannot work it out...