rust-embedded / rust-i2cdev

Rust library for interfacing with i2c devices under Linux
Apache License 2.0
204 stars 53 forks source link

Async IO #76

Open mpi3d opened 1 year ago

mpi3d commented 1 year ago

Hi,

Is it possible to have async functions binding in the same way that gpio_cdev::AsyncLineEventHandle does?

Is it as simple as opening the device file in non-blocking mode and warping the raw file descriptor in a tokio::io::unix::AsyncFd?

It would be very helpful to have an async API.

Thanks

mpi3d commented 1 year ago

Ok, so I tried to put the file in non-blocking mode using fcntl with O_NONBLOCK flag on the raw file descriptor. This works.

But then, when I use AsyncFd::new on the bus, it raises an "Operation not permitted" error.

After debugging, I realized that it's epoll_ctl call with the file descriptor that returns EPERM.

I didn't find anything useful on non-blocking I2C operations on Linux. So I'm not sure Linux support these.

mpi3d commented 1 year ago

After all, only dumb read and write operations would support async. Since all other operations use ioctl which are blocking.

So I guess the only way to have async is to spawn a tread to handle blocking I2C IO.

Unless someone has a better idea?

ryankurte commented 1 year ago

no idea how well it'll work, but, wrapping it in a smol::Async context and using read_with and write_with_mut is usually a good bet for anything implementing AsRawFd, so that might be worth a shot.

edit: looks like you're right, ioctls always block so it'd have to be a separate thread with channels

mpi3d commented 1 year ago

Do you think it's a good idea to provide async using threads in this crate. Or it should be up to the user of this crate to implement it?

ryankurte commented 1 year ago

hmm i think it'd be good to provide, though i wonder whether it would be better in linux-embedded-hal with the other e-h implementations / as an implementation of embedded-hal-async::i2c::I2c?

it will have to be runtime specific so probably behind a tokio feature, and if you're interested in implementing this be careful to use spawn_blocking to make sure the ioctl won't sleep the executor task.

mpi3d commented 1 year ago

Well, actually, I'm working on my own linux-embedded-hal-async. But if you want to merge it inside linux-embedded-hal, I would be happy to. Though, I'm currently focusing on async-std only.