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