1 /// The datatype used for the ioctl number
2 #[cfg(any(target_os = "android", target_env = "musl", target_env = "ohos"))]
3 #[doc(hidden)]
4 pub type ioctl_num_type = ::libc::c_int;
5 #[cfg(not(any(target_os = "android", target_env = "musl", target_env = "ohos")))]
6 #[doc(hidden)]
7 pub type ioctl_num_type = ::libc::c_ulong;
8 /// The datatype used for the 3rd argument
9 #[doc(hidden)]
10 pub type ioctl_param_type = ::libc::c_ulong;
11 
12 #[doc(hidden)]
13 pub const NRBITS: ioctl_num_type = 8;
14 #[doc(hidden)]
15 pub 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 ))]
24 mod 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 ))]
48 mod 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 
61 pub use self::consts::*;
62 
63 #[doc(hidden)]
64 pub const NRSHIFT: ioctl_num_type = 0;
65 #[doc(hidden)]
66 pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
67 #[doc(hidden)]
68 pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
69 #[doc(hidden)]
70 pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
71 
72 #[doc(hidden)]
73 pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
74 #[doc(hidden)]
75 pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
76 #[doc(hidden)]
77 pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
78 #[doc(hidden)]
79 pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
80 
81 /// Encode an ioctl command.
82 #[macro_export]
83 #[doc(hidden)]
84 macro_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)]
117 macro_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)]
134 macro_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)]
151 macro_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)]
164 macro_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