Skip to content

Commit 5d32538

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 e5a24d6 commit 5d32538

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
@@ -124,14 +124,49 @@
124124
//! There is also a `bad none`, `bad write`, and `bad readwrite` form that work similar to the
125125
//! standard `none`, `write`, and `readwrite` forms.
126126
//!
127+
//! Working with arrays
128+
//! --------------------
129+
//!
130+
//! Some `ioctl`s work with entire arrays of elements. These are supported by the `buf` suffix in
131+
//! the `ioctl!` macro which can be used by specifying `read buf`, `write buf`, and
132+
//! `readwrite buf`. Note that there are no "bad" versions for working with buffers. The generated
133+
//! functions include a `len` argument to specify the number of elements (where the type of each
134+
//! element is specified in the macro).
135+
//!
136+
//! Again looking to the SPI `ioctl`s on Linux for an example, `SPI_IOC_NR_TRANSFER` is an `ioctl`
137+
//! that queues up multiple SPI messages, so it writes an entire array of `spi_ioc_transfer`
138+
//! structs. This can be implemented like:
139+
//!
127140
//! ```
128141
//! # #[macro_use] extern crate nix;
129-
//! # use nix::libc::TIOCEXCL as TIOCEXCL;
130-
//! ioctl!(bad none tiocexcl with TIOCEXCL);
142+
//! # const SPI_IOC_MAGIC: nix::libc::c_int = 'k' as nix::libc::c_int;
143+
//! # const SPI_IOC_NR_TRANSFER: u8 = 0;
144+
//! # pub struct spi_ioc_transfer {
145+
//! # field1: u64,
146+
//! # }
147+
//! ioctl!(write buf spi_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
131148
//! # fn main() {}
132149
//! ```
133150
//!
134-
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
151+
//! This generates a function like:
152+
//!
153+
//! ```
154+
//! # #[macro_use] extern crate nix;
155+
//! # use nix::libc::c_int as c_int;
156+
//! # use nix::libc::c_ulong as c_ulong;
157+
//! # use std::mem;
158+
//! # use nix::{Errno, libc, Result};
159+
//! # const SPI_IOC_MAGIC: u8 = 'k' as u8;
160+
//! # const SPI_IOC_NR_TRANSFER: u8 = 0;
161+
//! # pub struct spi_ioc_transfer {
162+
//! # field1: u64,
163+
//! # }
164+
//! pub unsafe fn spi_transfer_buf(fd: c_int, data: *mut spi_ioc_transfer, len: usize) -> Result<c_int> {
165+
//! let res = libc::ioctl(fd, ior!(SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER, len * mem::size_of::<u8>()), data);
166+
//! Errno::result(res)
167+
//! }
168+
//! # fn main() {}
169+
//! ```
135170
//!
136171
//! Finding ioctl documentation
137172
//! ---------------------------
@@ -230,23 +265,23 @@ macro_rules! ioctl {
230265
data: *mut $ty,
231266
len: usize)
232267
-> $crate::Result<$crate::libc::c_int> {
233-
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
268+
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
234269
}
235270
);
236271
(write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
237272
pub unsafe fn $name(fd: $crate::libc::c_int,
238273
data: *const $ty,
239274
len: usize)
240275
-> $crate::Result<$crate::libc::c_int> {
241-
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
276+
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
242277
}
243278
);
244279
(readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
245280
pub unsafe fn $name(fd: $crate::libc::c_int,
246281
data: *mut $ty,
247282
len: usize)
248283
-> $crate::Result<$crate::libc::c_int> {
249-
convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data))
284+
convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
250285
}
251286
);
252287
}

0 commit comments

Comments
 (0)