Skip to content

Commit 26b75c7

Browse files
committed
Refactor ioctl! for buffers
Instead of relying on the macro user to calculate the length in bytes do that within the macro itself
1 parent c8cf6eb commit 26b75c7

File tree

1 file changed

+41
-6
lines changed

1 file changed

+41
-6
lines changed

src/sys/ioctl/mod.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,49 @@
120120
//! There is also a `bad none`, `bad write`, and `bad readwrite` form that work similar to the
121121
//! standard `none`, `write`, and `readwrite` forms.
122122
//!
123+
//! Working with arrays
124+
//! --------------------
125+
//!
126+
//! Some `ioctl`s work with entire arrays of elements. These are supported by the `buf` suffix in
127+
//! the `ioctl!` macro which can be used by specifying `read buf`, `write buf`, and
128+
//! `readwrite buf`. Note that there are no "bad" versions for working with buffers. The generated
129+
//! functions include a `len` argument to specify the number of elements (where the type of each
130+
//! element is specified in the macro).
131+
//!
132+
//! Again looking to the SPI `ioctl`s on Linux for an example, `SPI_IOC_NR_TRANSFER` is an `ioctl`
133+
//! that queues up multiple SPI messages, so it writes an entire array of `spi_ioc_transfer`
134+
//! structs. This can be implemented like:
135+
//!
123136
//! ```
124137
//! # #[macro_use] extern crate nix;
125-
//! # use nix::libc::TIOCEXCL as TIOCEXCL;
126-
//! ioctl!(bad none tiocexcl with TIOCEXCL);
138+
//! # const SPI_IOC_MAGIC: nix::libc::c_int = 'k' as nix::libc::c_int;
139+
//! # const SPI_IOC_NR_TRANSFER: u8 = 0;
140+
//! # pub struct spi_ioc_transfer {
141+
//! # field1: u64,
142+
//! # }
143+
//! ioctl!(write buf spi_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
127144
//! # fn main() {}
128145
//! ```
129146
//!
130-
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
147+
//! This generates a function like:
148+
//!
149+
//! ```
150+
//! # #[macro_use] extern crate nix;
151+
//! # use nix::libc::c_int as c_int;
152+
//! # use nix::libc::c_ulong as c_ulong;
153+
//! # use std::mem;
154+
//! # use nix::{Errno, libc, Result};
155+
//! # const SPI_IOC_MAGIC: u8 = 'k' as u8;
156+
//! # const SPI_IOC_NR_TRANSFER: u8 = 0;
157+
//! # pub struct spi_ioc_transfer {
158+
//! # field1: u64,
159+
//! # }
160+
//! pub unsafe fn spi_transfer_buf(fd: c_int, data: *mut spi_ioc_transfer, len: usize) -> Result<c_int> {
161+
//! let res = libc::ioctl(fd, ior!(SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER, len * mem::size_of::<u8>()), data);
162+
//! Errno::result(res)
163+
//! }
164+
//! # fn main() {}
165+
//! ```
131166
//!
132167
//! Finding ioctl documentation
133168
//! ---------------------------
@@ -226,23 +261,23 @@ macro_rules! ioctl {
226261
data: *mut $ty,
227262
len: usize)
228263
-> $crate::Result<$crate::libc::c_int> {
229-
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
264+
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
230265
}
231266
);
232267
(write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
233268
pub unsafe fn $name(fd: $crate::libc::c_int,
234269
data: *const $ty,
235270
len: usize)
236271
-> $crate::Result<$crate::libc::c_int> {
237-
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
272+
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
238273
}
239274
);
240275
(readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
241276
pub unsafe fn $name(fd: $crate::libc::c_int,
242277
data: *mut $ty,
243278
len: usize)
244279
-> $crate::Result<$crate::libc::c_int> {
245-
convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
280+
convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
246281
}
247282
);
248283
}

0 commit comments

Comments
 (0)