|
125 | 125 | //! There is also a `bad none`, `bad write`, and `bad readwrite` form that work similar to the
|
126 | 126 | //! standard `none`, `write`, and `readwrite` forms.
|
127 | 127 | //!
|
| 128 | +//! Working with arrays |
| 129 | +//! -------------------- |
| 130 | +//! |
| 131 | +//! Some `ioctl`s work with entire arrays of elements. These are supported by the `buf` suffix in |
| 132 | +//! the `ioctl!` macro which can be used by specifying `read buf`, `write buf`, and |
| 133 | +//! `readwrite buf`. Note that there are no "bad" versions for working with buffers. The generated |
| 134 | +//! functions include a `len` argument to specify the number of elements (where the type of each |
| 135 | +//! element is specified in the macro). |
| 136 | +//! |
| 137 | +//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl` |
| 138 | +//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs. |
| 139 | +//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like: |
| 140 | +//! |
| 141 | +//! ```C |
| 142 | +//! #define SPI_IOC_MAGIC 'k' |
| 143 | +//! #define SPI_MSGSIZE(N) ... |
| 144 | +//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) |
| 145 | +//! ``` |
| 146 | +//! |
| 147 | +//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl!` macro, so all that's |
| 148 | +//! needed to define this `ioctl` is: |
| 149 | +//! |
128 | 150 | //! ```
|
129 | 151 | //! # #[macro_use] extern crate nix;
|
130 |
| -//! # use nix::libc::TIOCEXCL as TIOCEXCL; |
131 |
| -//! ioctl!(bad none tiocexcl with TIOCEXCL); |
| 152 | +//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h |
| 153 | +//! const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
| 154 | +//! # pub struct spi_ioc_transfer(u64); |
| 155 | +//! ioctl!(write buf spi_transfer with SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE; spi_ioc_transfer); |
132 | 156 | //! # fn main() {}
|
133 | 157 | //! ```
|
134 | 158 | //!
|
135 |
| -//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev). |
| 159 | +//! This generates a function like: |
| 160 | +//! |
| 161 | +//! ``` |
| 162 | +//! # #[macro_use] extern crate nix; |
| 163 | +//! # use std::mem; |
| 164 | +//! # use nix::{Errno, libc, Result}; |
| 165 | +//! # use nix::libc::c_int as c_int; |
| 166 | +//! # const SPI_IOC_MAGIC: u8 = b'k'; |
| 167 | +//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
| 168 | +//! # pub struct spi_ioc_transfer(u64); |
| 169 | +//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> { |
| 170 | +//! let res = libc::ioctl(fd, iow!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()), data); |
| 171 | +//! Errno::result(res) |
| 172 | +//! } |
| 173 | +//! # fn main() {} |
| 174 | +//! ``` |
136 | 175 | //!
|
137 | 176 | //! Finding ioctl documentation
|
138 | 177 | //! ---------------------------
|
@@ -228,26 +267,23 @@ macro_rules! ioctl {
|
228 | 267 | );
|
229 | 268 | (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
|
230 | 269 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
231 |
| - data: *mut $ty, |
232 |
| - len: usize) |
| 270 | + data: &mut [$ty]) |
233 | 271 | -> $crate::Result<$crate::libc::c_int> {
|
234 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 272 | + 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)) |
235 | 273 | }
|
236 | 274 | );
|
237 | 275 | (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
|
238 | 276 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
239 |
| - data: *const $ty, |
240 |
| - len: usize) |
| 277 | + data: &[$ty]) |
241 | 278 | -> $crate::Result<$crate::libc::c_int> {
|
242 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 279 | + 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)) |
243 | 280 | }
|
244 | 281 | );
|
245 | 282 | (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
|
246 | 283 | pub unsafe fn $name(fd: $crate::libc::c_int,
|
247 |
| - data: *mut $ty, |
248 |
| - len: usize) |
| 284 | + data: &mut [$ty]) |
249 | 285 | -> $crate::Result<$crate::libc::c_int> {
|
250 |
| - convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::ioctl_num_type, data)) |
| 286 | + 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)) |
251 | 287 | }
|
252 | 288 | );
|
253 | 289 | }
|
0 commit comments