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