ioctl.rs18.56%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::mem::size_of;16
17
const IOC_NONN: u32 = 0;18
const IOC_WRITE: u32 = 1;19
const IOC_READ: u32 = 2;20
21
const IOC_NRSHIFT: usize = 0;22
const IOC_TYPESHIFT: usize = 8;23
const IOC_SIZESHIFT: usize = 16;24
const IOC_DIRSHIFT: usize = 30;25
26
const fn ioctl_ioc(dir: u32, type_: u8, nr: u8, size: u32) -> u32 {8x27
(dir << IOC_DIRSHIFT)8x28
| (size << IOC_SIZESHIFT)8x29
| ((type_ as u32) << IOC_TYPESHIFT)8x30
| ((nr as u32) << IOC_NRSHIFT)8x31
}8x32
33
pub const fn ioctl_io(type_: u8, nr: u8) -> u32 {2x34
ioctl_ioc(IOC_NONN, type_, nr, 0)2x35
}2x36
37
pub const fn ioctl_ior<T>(type_: u8, nr: u8) -> u32 {2x38
ioctl_ioc(IOC_READ, type_, nr, size_of::<T>() as u32)2x39
}2x40
41
pub const fn ioctl_iow<T>(type_: u8, nr: u8) -> u32 {2x42
ioctl_ioc(IOC_WRITE, type_, nr, size_of::<T>() as u32)2x43
}2x44
45
pub const fn ioctl_iowr<T>(type_: u8, nr: u8) -> u32 {2x46
ioctl_ioc(IOC_WRITE | IOC_READ, type_, nr, size_of::<T>() as u32)2x47
}2x48
49
#[macro_export]50
macro_rules! ioctl_none {51
($name:ident, $type_:expr, $nr:expr) => {52
#[allow(clippy::missing_safety_doc)]53
pub unsafe fn $name<F: ::std::os::fd::AsFd>(fd: &F) -> ::std::io::Result<libc::c_int> {54
let op = $crate::sys::ioctl::ioctl_io($type_, $nr);55
$crate::ffi!(unsafe {56
::libc::ioctl(::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()), op as _, 0)57
})58
}59
};60
}61
62
#[macro_export]63
macro_rules! ioctl_write_val {64
($name:ident, $code:expr, $ty:ty) => {65
#[allow(clippy::missing_safety_doc)]66
pub unsafe fn $name<F: ::std::os::fd::AsFd>(67
fd: &F,68
val: $ty,69
) -> ::std::io::Result<libc::c_int> {70
let op = $code;71
$crate::ffi!(unsafe {72
::libc::ioctl(::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()), op as _, val)73
})74
}75
};76
($name:ident, $type_:expr, $nr:expr, $ty:ty) => {77
$crate::ioctl_write_val!($name, $crate::sys::ioctl::ioctl_io($type_, $nr), $ty);78
};79
}80
81
#[macro_export]82
macro_rules! ioctl_write_ptr {83
($name:ident, $code:expr, $ty:ty) => {84
#[allow(clippy::missing_safety_doc)]85
pub unsafe fn $name<F: ::std::os::fd::AsFd>(86
fd: &F,87
val: &$ty,88
) -> ::std::io::Result<libc::c_int> {89
let op = $code;90
$crate::ffi!(unsafe {91
::libc::ioctl(92
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),93
op as _,94
val as *const $ty,95
)96
})97
}98
};99
($name:ident, $type_:expr, $nr:expr, $ty:ty) => {100
$crate::ioctl_write_ptr!(101
$name,102
$crate::sys::ioctl::ioctl_iow::<$ty>($type_, $nr),103
$ty104
);105
};106
}107
108
#[macro_export]109
macro_rules! ioctl_write_buf {110
($name:ident, $code:expr, $ty:ident) => {111
#[allow(clippy::missing_safety_doc)]112
pub unsafe fn $name<F: ::std::os::fd::AsFd, const N: usize>(113
fd: &F,114
val: &$ty<N>,115
) -> ::std::io::Result<libc::c_int> {116
let op = $code;117
$crate::ffi!(unsafe {118
::libc::ioctl(119
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),120
op as _,121
val as *const $ty<N>,122
)123
})124
}125
};126
($name:ident, $type_:expr, $nr:expr, $ty:ident) => {127
$crate::ioctl_write_buf!(128
$name,129
$crate::sys::ioctl::ioctl_iow::<$ty<0>>($type_, $nr),130
$ty131
);132
};133
}134
135
#[macro_export]136
macro_rules! ioctl_writeread {137
($name:ident, $code:expr, $ty:ty) => {138
#[allow(clippy::missing_safety_doc)]139
pub unsafe fn $name<F: ::std::os::fd::AsFd>(140
fd: &F,141
val: &mut $ty,142
) -> ::std::io::Result<libc::c_int> {143
let op = $code;144
$crate::ffi!(unsafe {145
::libc::ioctl(146
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),147
op as _,148
val as *mut $ty,149
)150
})151
}152
};153
($name:ident, $type_:expr, $nr:expr, $ty:ty) => {154
$crate::ioctl_writeread!(155
$name,156
$crate::sys::ioctl::ioctl_iowr::<$ty>($type_, $nr),157
$ty158
);159
};160
($name:ident, $code:expr) => {161
#[allow(clippy::missing_safety_doc)]162
pub unsafe fn $name<F: ::std::os::fd::AsFd, T>(163
fd: &F,164
val: &mut T,165
) -> ::std::io::Result<libc::c_int> {166
let op = $code;167
$crate::ffi!(unsafe {168
::libc::ioctl(169
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),170
op as _,171
val as *mut T,172
)173
})174
}175
};176
}177
178
#[macro_export]179
macro_rules! ioctl_writeread_buf {180
($name:ident, $code:expr, $ty:ident) => {181
#[allow(clippy::missing_safety_doc)]182
pub unsafe fn $name<F: ::std::os::fd::AsFd, const N: usize>(183
fd: &F,184
val: &mut $ty<N>,185
) -> ::std::io::Result<libc::c_int> {186
let op = $code;187
$crate::ffi!(unsafe {188
::libc::ioctl(189
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),190
op as _,191
val as *mut $ty<N>,192
)193
})194
}195
};196
($name:ident, $type_:expr, $nr:expr, $ty:ident) => {197
$crate::ioctl_writeread_buf!(198
$name,199
$crate::sys::ioctl::ioctl_iowr::<$ty<0>>($type_, $nr),200
$ty201
);202
};203
}204
205
#[macro_export]206
macro_rules! ioctl_read {207
($name:ident, $code:expr, $ty:ty) => {208
#[allow(clippy::missing_safety_doc)]209
pub unsafe fn $name<F: ::std::os::fd::AsFd>(fd: &F) -> ::std::io::Result<$ty> {210
let mut val = ::core::mem::MaybeUninit::<$ty>::uninit();211
let op = $code;212
$crate::ffi!(unsafe {213
::libc::ioctl(214
::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),215
op as _,216
val.as_mut_ptr(),217
)218
})?;219
::std::io::Result::Ok(unsafe { val.assume_init() })220
}221
};222
($name:ident, $type_:expr, $nr:expr, $ty:ty) => {223
$crate::ioctl_read!(224
$name,225
$crate::sys::ioctl::ioctl_ior::<$ty>($type_, $nr),226
$ty227
);228
};229
}230
231
#[cfg(test)]232
#[path = "ioctl_test.rs"]233
mod tests;234