nix/sys/ioctl/
linux.rs

1use cfg_if::cfg_if;
2
3/// The datatype used for the ioctl number
4#[cfg(any(
5    target_os = "android",
6    target_os = "fuchsia",
7    target_env = "musl",
8    target_env = "ohos"
9))]
10#[doc(hidden)]
11pub type ioctl_num_type = ::libc::c_int;
12#[cfg(not(any(
13    target_os = "android",
14    target_os = "fuchsia",
15    target_env = "musl",
16    target_env = "ohos"
17)))]
18#[doc(hidden)]
19pub type ioctl_num_type = ::libc::c_ulong;
20/// The datatype used for the 3rd argument
21#[doc(hidden)]
22pub type ioctl_param_type = ::libc::c_ulong;
23
24#[doc(hidden)]
25pub const NRBITS: ioctl_num_type = 8;
26#[doc(hidden)]
27pub const TYPEBITS: ioctl_num_type = 8;
28
29cfg_if! {
30    if #[cfg(any(
31        target_arch = "mips",
32        target_arch = "mips32r6",
33        target_arch = "mips64",
34        target_arch = "mips64r6",
35        target_arch = "powerpc",
36        target_arch = "powerpc64",
37        target_arch = "sparc64"
38    ))] {
39        mod consts {
40            #[doc(hidden)]
41            pub const NONE: u8 = 1;
42            #[doc(hidden)]
43            pub const READ: u8 = 2;
44            #[doc(hidden)]
45            pub const WRITE: u8 = 4;
46            #[doc(hidden)]
47            pub const SIZEBITS: u8 = 13;
48            #[doc(hidden)]
49            pub const DIRBITS: u8 = 3;
50        }
51    } else {
52        // "Generic" ioctl protocol
53        mod consts {
54            #[doc(hidden)]
55            pub const NONE: u8 = 0;
56            #[doc(hidden)]
57            pub const READ: u8 = 2;
58            #[doc(hidden)]
59            pub const WRITE: u8 = 1;
60            #[doc(hidden)]
61            pub const SIZEBITS: u8 = 14;
62            #[doc(hidden)]
63            pub const DIRBITS: u8 = 2;
64        }
65    }
66}
67
68pub use self::consts::*;
69
70#[doc(hidden)]
71pub const NRSHIFT: ioctl_num_type = 0;
72#[doc(hidden)]
73pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
74#[doc(hidden)]
75pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
76#[doc(hidden)]
77pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
78
79#[doc(hidden)]
80pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
81#[doc(hidden)]
82pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
83#[doc(hidden)]
84pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
85#[doc(hidden)]
86pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
87
88/// Encode an ioctl command.
89#[macro_export]
90#[doc(hidden)]
91macro_rules! ioc {
92    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => {
93        (($dir as $crate::sys::ioctl::ioctl_num_type
94            & $crate::sys::ioctl::DIRMASK)
95            << $crate::sys::ioctl::DIRSHIFT)
96            | (($ty as $crate::sys::ioctl::ioctl_num_type
97                & $crate::sys::ioctl::TYPEMASK)
98                << $crate::sys::ioctl::TYPESHIFT)
99            | (($nr as $crate::sys::ioctl::ioctl_num_type
100                & $crate::sys::ioctl::NRMASK)
101                << $crate::sys::ioctl::NRSHIFT)
102            | (($sz as $crate::sys::ioctl::ioctl_num_type
103                & $crate::sys::ioctl::SIZEMASK)
104                << $crate::sys::ioctl::SIZESHIFT)
105    };
106}
107
108/// Generate an ioctl request code for a command that passes no data.
109///
110/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
111///
112/// You should only use this macro directly if the `ioctl` you're working
113/// with is "bad" and you cannot use `ioctl_none!()` directly.
114///
115/// # Example
116///
117/// ```
118/// # #[macro_use] extern crate nix;
119/// const KVMIO: u8 = 0xAE;
120/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
121/// # fn main() {}
122/// ```
123#[macro_export(local_inner_macros)]
124macro_rules! request_code_none {
125    ($ty:expr, $nr:expr) => {
126        ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0)
127    };
128}
129
130/// Generate an ioctl request code for a command that reads.
131///
132/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
133///
134/// You should only use this macro directly if the `ioctl` you're working
135/// with is "bad" and you cannot use `ioctl_read!()` directly.
136///
137/// The read/write direction is relative to userland, so this
138/// command would be userland is reading and the kernel is
139/// writing.
140#[macro_export(local_inner_macros)]
141macro_rules! request_code_read {
142    ($ty:expr, $nr:expr, $sz:expr) => {
143        ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz)
144    };
145}
146
147/// Generate an ioctl request code for a command that writes.
148///
149/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
150///
151/// You should only use this macro directly if the `ioctl` you're working
152/// with is "bad" and you cannot use `ioctl_write!()` directly.
153///
154/// The read/write direction is relative to userland, so this
155/// command would be userland is writing and the kernel is
156/// reading.
157#[macro_export(local_inner_macros)]
158macro_rules! request_code_write {
159    ($ty:expr, $nr:expr, $sz:expr) => {
160        ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz)
161    };
162}
163
164/// Generate an ioctl request code for a command that reads and writes.
165///
166/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
167///
168/// You should only use this macro directly if the `ioctl` you're working
169/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
170#[macro_export(local_inner_macros)]
171macro_rules! request_code_readwrite {
172    ($ty:expr, $nr:expr, $sz:expr) => {
173        ioc!(
174            $crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE,
175            $ty,
176            $nr,
177            $sz
178        )
179    };
180}