ioctl_id/
linux.rs

1//! Linux-specific definitions.
2//!
3//! On Linux, `ioctl(2)` identifiers are the size of C's `unsigned long` type,
4//! equivalent to `u32` on 32-bit architectures and `u64` on 64-bit
5//! architectures.
6//!
7//! The `ioctl(2)` identifier is divided into four fields. From most-significant to least-significant in the identifier:
8//! * The direction of the `ioctl(2)` call.
9//! * The size of the structure passed to the `ioctl(2)` call.
10//! * A type identifier.
11//! * A call identifier.
12//!
13//! The size of these fields varies by platform.
14
15use core::{ffi::c_ulong, mem::size_of};
16
17/// The identifier type for ioctl calls.
18pub type IoctlId = c_ulong;
19
20/// This is the same for all architectures.
21///
22/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L23)
23pub const IOC_NRBITS: usize = 8;
24
25/// The number of bits available for `ioctl(2)` type identifiers.
26///
27/// This is the same for all architectures.
28///
29/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L24)
30pub const IOC_TYPEBITS: usize = 8;
31
32/// The number of bits used to represent the size of the argument to the `ioctl(2)` call.
33///
34/// For Alpha (not supported by Rust), MIPS, and PowerPC, this is 13 bits. For all other architectures, this is 14 bits.
35///
36/// For SPARC, this is 14 bits with an [overlap on the direction field](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L6-L8).
37///
38/// References:
39/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L6)
40/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L14)
41/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L5)
42/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L32)
43#[cfg(any(
44    target_arch = "mips",
45    target_arch = "mips64",
46    target_arch = "mips64r6",
47    target_arch = "powerpc",
48    target_arch = "powerpc64"
49))]
50pub const IOC_SIZEBITS: usize = 13;
51
52/// The number of bits used to represent the size of the argument to the `ioctl(2)` call.
53///
54/// For Alpha (not supported by Rust), MIPS, and PowerPC, this is 13 bits. For all other architectures, this is 14 bits.
55///
56/// For SPARC, this is 14 bits with an
57/// [overlap on the direction field](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L6-L8).
58///
59/// References:
60/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L6)
61/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L14)
62/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L5)
63/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L32)
64#[cfg(not(any(
65    target_arch = "mips",
66    target_arch = "mips64",
67    target_arch = "mips64r6",
68    target_arch = "powerpc",
69    target_arch = "powerpc64"
70)))]
71pub const IOC_SIZEBITS: usize = 14;
72
73/// The number of bits used to represent the direction of the `ioctl(2)` call.
74///
75/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 3 bits. For all other architectures, this is
76/// 2 bits.
77///
78/// Note that on SPARC the direction field
79/// [overlaps with the size field](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L6-L8).
80///
81/// References:
82/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L19)
83/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L15)
84/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L22)
85/// * SPARC: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L22)
86/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L36)
87#[cfg(any(
88    target_arch = "mips",
89    target_arch = "mips64",
90    target_arch = "mips64r6",
91    target_arch = "powerpc",
92    target_arch = "sparc",
93    target_arch = "sparc64"
94))]
95pub const IOC_DIRBITS: usize = 3;
96
97/// The number of bits used to represent the direction of the `ioctl(2)` call.
98///
99/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 3 bits. For all other architectures, this is
100/// 2 bits.
101///
102/// Note that on SPARC the direction field
103/// [overlaps with the size field](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L6-L8).
104///
105/// References:
106/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L19)
107/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L15)
108/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L22)
109/// * SPARC: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L22)
110/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L36)
111#[cfg(not(any(
112    target_arch = "mips",
113    target_arch = "mips64",
114    target_arch = "mips64r6",
115    target_arch = "powerpc",
116    target_arch = "sparc",
117    target_arch = "sparc64"
118)))]
119pub const IOC_DIRBITS: usize = 2;
120
121/// Direction bit specifying no data is read or written.
122///
123/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 1. For all other architectures, this is
124/// 0 (no bits are set).
125///
126/// References:
127/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L36)
128/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L22)
129/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L8)
130/// * Sparc: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L35)
131/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L35)
132#[cfg(any(
133    target_arch = "mips",
134    target_arch = "mips64",
135    target_arch = "mips64r6",
136    target_arch = "powerpc",
137    target_arch = "sparc",
138    target_arch = "sparc64"
139))]
140pub const IOC_NONE: IoctlId = 1;
141
142/// Direction bit specifying no data is read or written.
143///
144/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 1. For all other architectures, this is
145/// 0 (no bits are set).
146///
147/// References:
148/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L36)
149/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L22)
150/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L8)
151/// * Sparc: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L35)
152/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L58)
153#[cfg(not(any(
154    target_arch = "mips",
155    target_arch = "mips64",
156    target_arch = "mips64r6",
157    target_arch = "powerpc",
158    target_arch = "sparc",
159    target_arch = "sparc64"
160)))]
161pub const IOC_NONE: IoctlId = 0;
162
163/// Direction bit specifying data is read.
164///
165/// This is 2 on all platforms (except PA-RISC, which is not supported by Rust).
166///
167/// References:
168/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L37)
169/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L23)
170/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L9)
171/// * Sparc: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L36)
172/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L62)
173pub const IOC_READ: IoctlId = 2;
174
175/// Direction bit specifying data is written.
176///
177/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 4. For PA-RISC (not supported by Rust), this
178/// is 2. For all other architectures, this is 1.
179///
180/// References:
181/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L38)
182/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L24)
183/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L10)
184/// * Sparc: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L37)
185/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L66)
186#[cfg(any(
187    target_arch = "mips",
188    target_arch = "mips64",
189    target_arch = "mips64r6",
190    target_arch = "powerpc",
191    target_arch = "sparc",
192    target_arch = "sparc64"
193))]
194pub const IOC_WRITE: IoctlId = 4;
195
196/// Direction bit specifying data is written.
197///
198/// For Alpha (not supported by Rust), MIPS, PowerPC, and SPARC, this is 4. For PA-RISC (not supported by Rust), this
199/// is 2. For all other architectures, this is 1.
200///
201/// References:
202/// * Alpha: [`arch/alpha/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/alpha/include/uapi/asm/ioctl.h#L38)
203/// * MIPS: [`arch/mips/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/mips/include/uapi/asm/ioctl.h#L24)
204/// * PowerPC: [`arch/powerpc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/powerpc/include/uapi/asm/ioctl.h#L10)
205/// * Sparc: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L37)
206/// * All others: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L66)
207#[cfg(not(any(
208    target_arch = "mips",
209    target_arch = "mips64",
210    target_arch = "mips64r6",
211    target_arch = "powerpc",
212    target_arch = "sparc",
213    target_arch = "sparc64"
214)))]
215pub const IOC_WRITE: IoctlId = 1;
216
217/// Bitmask for valid `ioctl(2)` call identifiers.
218///
219/// This is applied to the unshifted call identifier.
220///
221/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L39)
222pub const IOC_NRMASK: IoctlId = (1 << IOC_NRBITS) - 1;
223
224/// Bitmask for valid `ioctl(2)` type identifiers.
225///
226/// This is applied to the unshifted type identifier.
227///
228/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L40)
229pub const IOC_TYPEMASK: IoctlId = (1 << IOC_TYPEBITS) - 1;
230
231/// Bitmask for valid `ioctl(2)` size values.
232///
233/// This is applied to the unshifted size value.
234///
235/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L41)
236pub const IOC_SIZEMASK: IoctlId = (1 << IOC_SIZEBITS) - 1;
237
238/// Bitmask for valid `ioctl(2)` direction values.
239///
240/// This is applied to the unshifted direction value.
241///
242/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L42)
243pub const IOC_DIRMASK: IoctlId = (1 << IOC_DIRBITS) - 1;
244
245/// The number of bits to shift `ioctl(2)` call identifiers by.
246///
247/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L44)
248pub const IOC_NRSHIFT: usize = 0;
249
250/// The number of bits to shift `ioctl(2)` type identifiers by.
251///
252/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L45)
253pub const IOC_TYPESHIFT: usize = IOC_NRSHIFT + IOC_NRBITS;
254
255/// The number of bits to shift `ioctl(2)` size values by.
256///
257/// For SPARC, this is decremented by 1 to account for the overlap with the direction field.
258///
259/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L46)
260#[cfg(target_arch = "sparc")]
261///
262/// SPARC Reference: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L26-L32)
263pub const IOC_SIZESHIFT: usize = IOC_TYPESHIFT + IOC_TYPEBITS - 1;
264
265/// The number of bits to shift `ioctl(2)` size values by.
266///
267/// For SPARC, this is decremented by 1 to account for the overlap with the direction field.
268///
269/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L46)
270///
271/// SPARC Reference: [`arch/sparc/include/uapi/asm/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/arch/sparc/include/uapi/asm/ioctl.h#L26-L32)
272#[cfg(not(target_arch = "sparc"))]
273pub const IOC_SIZESHIFT: usize = IOC_TYPESHIFT + IOC_TYPEBITS;
274
275/// The number of bits to shift `ioctl(2)` direction values by.
276///
277/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L47)
278pub const IOC_DIRSHIFT: usize = IOC_SIZESHIFT + IOC_SIZEBITS;
279
280/// Create an `ioctl(2)` identifier from a direction value, type identifier,
281/// call identifier, and size value.
282///
283/// Note that the order of the parameters does not match their shift values. This matches the definition of the
284/// `_IOC()` macro from the C headers.
285///
286/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L69-L73)
287pub const fn ioc(dir: IoctlId, r#type: IoctlId, nr: IoctlId, size: IoctlId) -> IoctlId {
288    (dir << IOC_DIRSHIFT) | (r#type << IOC_TYPESHIFT) | (nr << IOC_NRSHIFT) | (size << IOC_SIZESHIFT)
289}
290
291/// Create an `ioctl(2)` identifier for a call that passes no data.
292///
293/// This is the equivalent of the `_IO()` macro from the C headers.
294///
295/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L85)
296pub const fn io(r#type: IoctlId, nr: IoctlId) -> IoctlId {
297    ioc(IOC_NONE, r#type, nr, 0)
298}
299
300/// Create an `ioctl(2)` identifier for a call that reads data.
301///
302/// This is the equivalent of the `_IOR()` macro from the C headers. The type must be passed as a generic parameter
303/// to this function.
304///
305/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L86)
306pub const fn ior<T>(r#type: IoctlId, nr: IoctlId) -> IoctlId {
307    ioc(IOC_READ, r#type, nr, size_of::<T>() as IoctlId)
308}
309
310/// Create an `ioctl(2)` identifier for a call that writes data.
311///
312/// This is the equivalent of the `_IOW()` macro from the C headers. The type must be passed as a generic parameter
313/// to this function.
314///
315/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L86)
316pub const fn iow<T>(r#type: IoctlId, nr: IoctlId) -> IoctlId {
317    ioc(IOC_WRITE, r#type, nr, size_of::<T>() as IoctlId)
318}
319
320/// Create an `ioctl(2)` identifier for a call that reads and writes data.
321///
322/// This is the equivalent of the `_IOWR()` macro from the C headers. The type must be passed as a generic parameter
323/// to this function.
324///
325/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L87)
326pub const fn iowr<T>(r#type: IoctlId, nr: IoctlId) -> IoctlId {
327    ioc(IOC_READ | IOC_WRITE, r#type, nr, size_of::<T>() as IoctlId)
328}
329
330/// Decode the direction value from an `ioctl(2)` identifier.
331///
332/// This is the equivalent of the `_IOC_DIR()` macro from the C headers.
333///
334/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L94)
335pub const fn ioc_dir(id: IoctlId) -> IoctlId {
336    (id >> IOC_DIRSHIFT) & IOC_DIRMASK
337}
338
339/// Decode the type identifier from an `ioctl(2)` identifier.
340///
341/// This is the equivalent of the `_IOC_TYPE()` macro from the C headers.
342///
343/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L95)
344pub const fn ioc_type(id: IoctlId) -> IoctlId {
345    (id >> IOC_TYPESHIFT) & IOC_TYPEMASK
346}
347
348/// Decode the call identifier from an `ioctl(2)` identifier.
349///
350/// This is the equivalent of the `_IOC_NR()` macro from the C headers.
351///
352/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L96)
353pub const fn ioc_nr(id: IoctlId) -> IoctlId {
354    (id >> IOC_NRSHIFT) & IOC_NRMASK
355}
356
357/// Decode the size identifier from an `ioctl(2)` identifier.
358///
359/// This is the equivalent of the `_IOC_SIZE()` macro from the C headers.
360///
361/// Reference: [`include/uapi/asm-generic/ioctl.h`](https://github.com/torvalds/linux/blob/7c16f0a4ed1ce7b0dd1c01fc012e5bde89fe7748/include/uapi/asm-generic/ioctl.h#L97)
362pub const fn ioc_size(id: IoctlId) -> IoctlId {
363    (id >> IOC_SIZESHIFT) & IOC_SIZEMASK
364}