diff options
-rw-r--r-- | src/sys/ioctl/mod.rs | 55 | ||||
-rw-r--r-- | test/sys/test_ioctl.rs | 7 |
2 files changed, 44 insertions, 18 deletions
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs index 058fc60a..f54384e6 100644 --- a/src/sys/ioctl/mod.rs +++ b/src/sys/ioctl/mod.rs @@ -108,35 +108,37 @@ //! //! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev). //! -//! ```text -//! pub unsafe fn $NAME(fd: c_int, data: *mut u8, len: usize) -> Result<c_int>; -//! ``` +//! Using hard-coded ioctl numbers +//! ------------------------------ //! //! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of -//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad` -//! form of the `ioctl!` macro (there is no data transfer direction used with `bad`). The naming of -//! this comes from the Linux kernel which refers to these `ioctl`s as "bad". +//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad *` +//! variants of the `ioctl!` macro. This naming comes from the Linux kernel which refers to these +//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates +//! the ioctl number and instead use the defined value directly. //! //! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor. -//! It can be implemented as: +//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as: //! //! ``` //! # #[macro_use] extern crate nix; //! # #[cfg(any(target_os = "android", target_os = "linux"))] //! # use nix::libc::TCGETS as TCGETS; //! # #[cfg(any(target_os = "android", target_os = "linux"))] -//! ioctl!(bad tcgets with TCGETS); +//! # use nix::libc::termios as termios; +//! # #[cfg(any(target_os = "android", target_os = "linux"))] +//! ioctl!(bad read tcgets with TCGETS; termios); //! # fn main() {} //! ``` //! //! The generated function has the same form as that generated by `read`: //! //! ```text -//! pub unsafe fn tcgets(fd: c_int, data: *mut u8) -> Result<c_int>; +//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>; //! ``` //! -//! There is also a `bad none` form for use with hard-coded `ioctl`s that do not transfer data. -//! The `TIOCEXCL` `ioctl` that's part of the termios API can be implemented as: +//! There is also a `bad none`, `bad write_int`/`bad write_ptr`, and `bad readwrite` variant that work +//! similar to the standard `none`, `write_int`/`write_ptr`, and `readwrite` variants. //! //! ``` //! # #[macro_use] extern crate nix; @@ -185,17 +187,38 @@ macro_rules! convert_ioctl_res { /// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html). #[macro_export] macro_rules! ioctl { - (bad $name:ident with $nr:expr) => ( + (bad none $name:ident with $nr:expr) => ( + pub unsafe fn $name(fd: $crate::libc::c_int) + -> $crate::Result<$crate::libc::c_int> { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type)) + } + ); + (bad read $name:ident with $nr:expr; $ty:ty) => ( pub unsafe fn $name(fd: $crate::libc::c_int, - data: *mut u8) + data: *mut $ty) -> $crate::Result<$crate::libc::c_int> { convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) } ); - (bad none $name:ident with $nr:expr) => ( - pub unsafe fn $name(fd: $crate::libc::c_int) + (bad write_ptr $name:ident with $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::libc::c_int, + data: *const $ty) -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type)) + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) + } + ); + (bad write_int $name:ident with $nr:expr) => ( + pub unsafe fn $name(fd: $crate::libc::c_int, + data: $crate::libc::c_int) + -> $crate::Result<$crate::libc::c_int> { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) + } + ); + (bad readwrite $name:ident with $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::libc::c_int, + data: *mut $ty) + -> $crate::Result<$crate::libc::c_int> { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) } ); (none $name:ident with $ioty:expr, $nr:expr) => ( diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs index 7f0018d3..18432266 100644 --- a/test/sys/test_ioctl.rs +++ b/test/sys/test_ioctl.rs @@ -1,8 +1,11 @@ #![allow(dead_code)] // Simple tests to ensure macro generated fns compile -ioctl!(bad do_bad with 0x1234); -ioctl!(bad none do_bad_none with 0x1234); +ioctl!(bad none do_bad with 0x1234); +ioctl!(bad read do_bad_read with 0x1234; u16); +ioctl!(bad write_int do_bad_write_int with 0x1234); +ioctl!(bad write_ptr do_bad_write_ptr with 0x1234; u8); +ioctl!(bad readwrite do_bad_readwrite with 0x1234; u32); ioctl!(none do_none with 0, 0); ioctl!(read read_test with 0, 0; u32); ioctl!(write_int write_ptr_int with 0, 0); |