Skip to main content

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