|
140 | 140 | //! There is also a `bad none`, `bad write_int`/`bad write_ptr`, and `bad readwrite` variant that work
|
141 | 141 | //! similar to the standard `none`, `write_int`/`write_ptr`, and `readwrite` variants.
|
142 | 142 | //!
|
| 143 | +//! Working with arrays |
| 144 | +//! -------------------- |
| 145 | +//! |
| 146 | +//! Some `ioctl`s work with entire arrays of elements. These are supported by the `*_buf` variants in |
| 147 | +//! the `ioctl!` macro which can be used by specifying `read_buf`, `write_buf`, and |
| 148 | +//! `readwrite_buf`. Note that there are no "bad" versions for working with buffers. The generated |
| 149 | +//! functions include a `len` argument to specify the number of elements (where the type of each |
| 150 | +//! element is specified in the macro). |
| 151 | +//! |
| 152 | +//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl` |
| 153 | +//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs. |
| 154 | +//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like: |
| 155 | +//! |
| 156 | +//! ```C |
| 157 | +//! #define SPI_IOC_MAGIC 'k' |
| 158 | +//! #define SPI_MSGSIZE(N) ... |
| 159 | +//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) |
| 160 | +//! ``` |
| 161 | +//! |
| 162 | +//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl!` macro, so all that's |
| 163 | +//! needed to define this `ioctl` is: |
| 164 | +//! |
143 | 165 | //! ```
|
144 | 166 | //! # #[macro_use] extern crate nix;
|
145 |
| -//! # use nix::libc::TIOCEXCL as TIOCEXCL; |
146 |
| -//! ioctl!(bad none tiocexcl with TIOCEXCL); |
| 167 | +//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h |
| 168 | +//! const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
| 169 | +//! # pub struct spi_ioc_transfer(u64); |
| 170 | +//! ioctl!(write_buf spi_transfer with SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE; spi_ioc_transfer); |
147 | 171 | //! # fn main() {}
|
148 | 172 | //! ```
|
149 | 173 | //!
|
150 |
| -//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev). |
| 174 | +//! This generates a function like: |
| 175 | +//! |
| 176 | +//! ``` |
| 177 | +//! # #[macro_use] extern crate nix; |
| 178 | +//! # use std::mem; |
| 179 | +//! # use nix::{Errno, libc, Result}; |
| 180 | +//! # use nix::libc::c_int as c_int; |
| 181 | +//! # const SPI_IOC_MAGIC: u8 = b'k'; |
| 182 | +//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
| 183 | +//! # pub struct spi_ioc_transfer(u64); |
| 184 | +//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> { |
| 185 | +//! let res = libc::ioctl(fd, |
| 186 | +//! iow!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()), |
| 187 | +//! data); |
| 188 | +//! Errno::result(res) |
| 189 | +//! } |
| 190 | +//! # fn main() {} |
| 191 | +//! ``` |
151 | 192 | //!
|
152 | 193 | //! Finding ioctl documentation
|
153 | 194 | //! ---------------------------
|
@@ -255,28 +296,25 @@ macro_rules! ioctl {
|
255 | 296 | convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
|
256 | 297 | }
|
257 | 298 | );
|
258 |
| - (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
| 299 | + (read_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
259 | 300 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
260 |
| - data: *mut $ty, |
261 |
| - len: usize) |
| 301 | + data: &mut [$ty]) |
262 | 302 | -> $crate::Result<$crate::libc::c_int> {
|
263 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 303 | + convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
264 | 304 | }
|
265 | 305 | );
|
266 |
| - (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
| 306 | + (write_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
267 | 307 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
268 |
| - data: *const $ty, |
269 |
| - len: usize) |
| 308 | + data: &[$ty]) |
270 | 309 | -> $crate::Result<$crate::libc::c_int> {
|
271 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 310 | + convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
272 | 311 | }
|
273 | 312 | );
|
274 |
| - (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
| 313 | + (readwrite_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( |
275 | 314 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
276 |
| - data: *mut $ty, |
277 |
| - len: usize) |
| 315 | + data: &mut [$ty]) |
278 | 316 | -> $crate::Result<$crate::libc::c_int> {
|
279 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 317 | + convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
280 | 318 | }
|
281 | 319 | );
|
282 | 320 | }
|
0 commit comments