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