Skip to content

Commit

Permalink
Implement equivalent for _IOWINT for FreeBSD-like targets
Browse files Browse the repository at this point in the history
ioctls on FreeBSD and DragonflyBSD have a separate request code generation
macro `_IOWINT` which is now exposed as `request_code_write_int`.

`ioctl_write_int` is also fixed on these platforms to use this new request
  • Loading branch information
Bryant Mairs committed Jan 30, 2018
1 parent b11a3c6 commit 957ec87
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 34 deletions.
11 changes: 11 additions & 0 deletions src/sys/ioctl/bsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ macro_rules! request_code_none {
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
}

/// Generate an ioctl request code for a command that passes an integer
///
/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
#[macro_export]
macro_rules! request_code_write_int {
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>()))
}

/// Generate an ioctl request code for a command that reads.
///
/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
Expand Down
107 changes: 73 additions & 34 deletions src/sys/ioctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,41 +511,80 @@ macro_rules! ioctl_write_ptr_bad {
)
}

/// Generates a wrapper function for a ioctl that writes an integer to the kernel.
///
/// The arguments to this macro are:
///
/// * The function name
/// * The ioctl identifier
/// * The ioctl sequence number
///
/// The generated function has the following signature:
///
/// ```rust,ignore
/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
/// ```
///
/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nix;
/// const HCI_IOC_MAGIC: u8 = b'k';
/// const HCI_IOC_HCIDEVUP: u8 = 1;
/// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! ioctl_write_int {
($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
$(#[$attr])*
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, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
cfg_if!{
if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
/// Generates a wrapper function for a ioctl that writes an integer to the kernel.
///
/// The arguments to this macro are:
///
/// * The function name
/// * The ioctl identifier
/// * The ioctl sequence number
///
/// The generated function has the following signature:
///
/// ```rust,ignore
/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
/// ```
///
/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nix;
/// ioctl_write_int!(vt_activate, b'v', 4);
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! ioctl_write_int {
($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
$(#[$attr])*
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, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
}
)
}
)
} else {
/// Generates a wrapper function for a ioctl that writes an integer to the kernel.
///
/// The arguments to this macro are:
///
/// * The function name
/// * The ioctl identifier
/// * The ioctl sequence number
///
/// The generated function has the following signature:
///
/// ```rust,ignore
/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
/// ```
///
/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nix;
/// const HCI_IOC_MAGIC: u8 = b'k';
/// const HCI_IOC_HCIDEVUP: u8 = 1;
/// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! ioctl_write_int {
($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
$(#[$attr])*
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, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
)
}
}
}

/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
Expand Down
7 changes: 7 additions & 0 deletions test/sys/test_ioctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ mod bsd {
assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
}

#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[test]
fn test_op_write_int() {
assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
}

#[test]
fn test_op_write() {
assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
Expand Down

0 comments on commit 957ec87

Please sign in to comment.