use core::mem::MaybeUninit;
use linux_unsafe::args::AsRawV;
use linux_unsafe::{int, ulong};
pub trait IoDevice {}
pub unsafe trait SubDevice<Parent: IoDevice>: IoDevice {}
unsafe impl<T: IoDevice> SubDevice<T> for T {}
pub unsafe trait IoctlReq<'a, Device: IoDevice>: Copy {
type ExtArg
where
Self: 'a;
type TempMem;
type RawArg: AsRawV;
type Result
where
Self: 'a;
fn prepare_ioctl_args(
&self,
arg: &Self::ExtArg,
temp_mem: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, Self::RawArg);
fn prepare_ioctl_result(
&self,
raw: int,
arg: &Self::ExtArg,
temp_mem: &MaybeUninit<Self::TempMem>,
) -> Self::Result;
}
pub const unsafe fn ioctl_no_arg<Device, Result>(request: ulong) -> IoctlReqNoArgs<Device, Result>
where
*mut Result: AsRawV,
Device: IoDevice,
Result: FromIoctlResult<int>,
{
IoctlReqNoArgs::<Device, Result> {
request,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn ioctl_const_arg<Device, Result, const ARG: int>(
request: ulong,
) -> IoctlReqConstArg<Device, Result, ARG>
where
*mut Result: AsRawV,
Device: IoDevice,
Result: FromIoctlResult<int>,
{
IoctlReqConstArg::<Device, Result, ARG> {
request,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn ioctl_read<Device, Result>(request: ulong) -> IoctlReqRead<Device, Result>
where
*mut Result: AsRawV,
Device: IoDevice,
Result: Copy,
{
IoctlReqRead::<Device, Result> {
request,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn ioctl_write_val<Device, Arg, Result>(
request: ulong,
) -> IoctlReqWriteVal<Device, Arg, Result>
where
Arg: AsRawV,
Device: IoDevice,
Result: FromIoctlResult<int>,
{
IoctlReqWriteVal::<Device, Arg, Result> {
request,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn ioctl_write<Device, Arg, Result>(
request: ulong,
) -> IoctlReqWrite<Device, Arg, Result>
where
*const Arg: AsRawV,
Device: IoDevice,
Result: FromIoctlResult<int>,
{
IoctlReqWrite::<Device, Arg, Result> {
request,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn ioctl_writeread<Device, Arg, Result>(
request: ulong,
) -> IoctlReqWriteRead<Device, Arg, Result>
where
*mut Result: AsRawV,
Device: IoDevice,
Result: Copy,
{
IoctlReqWriteRead::<Device, Arg, Result> {
request,
_phantom: core::marker::PhantomData,
}
}
#[repr(transparent)]
pub struct IoctlReqNoArgs<Device: IoDevice, Result> {
request: ulong,
_phantom: core::marker::PhantomData<(Device, Result)>,
}
impl<Device: IoDevice, Result> Clone for IoctlReqNoArgs<Device, Result> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Result> Copy for IoctlReqNoArgs<Device, Result> {}
unsafe impl<'a, Device, Result> IoctlReq<'a, Device> for IoctlReqNoArgs<Device, Result>
where
Result: 'a + FromIoctlResult<int>,
Device: 'a + IoDevice,
{
type ExtArg = ();
type TempMem = ();
type RawArg = ();
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
_: &Self::ExtArg,
_: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, Self::RawArg) {
(self.request, ())
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
raw: int,
_: &Self::ExtArg,
_: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
Self::Result::from_ioctl_result(&raw)
}
}
#[repr(transparent)]
pub struct IoctlReqConstArg<Device: IoDevice, Result, const ARG: int> {
request: ulong,
_phantom: core::marker::PhantomData<(Device, Result)>,
}
impl<Device: IoDevice, Result, const ARG: int> Clone for IoctlReqConstArg<Device, Result, ARG> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Result, const ARG: int> Copy for IoctlReqConstArg<Device, Result, ARG> {}
unsafe impl<'a, Device, Result, const ARG: int> IoctlReq<'a, Device>
for IoctlReqConstArg<Device, Result, ARG>
where
Result: 'a + FromIoctlResult<int>,
Device: 'a + IoDevice,
{
type ExtArg = ();
type TempMem = ();
type RawArg = int;
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
_: &Self::ExtArg,
_: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, Self::RawArg) {
(self.request, ARG)
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
raw: int,
_: &Self::ExtArg,
_: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
Self::Result::from_ioctl_result(&raw)
}
}
#[repr(transparent)]
pub struct IoctlReqRead<Device: IoDevice, Result>
where
*mut Result: AsRawV,
Result: Copy,
{
request: ulong,
_phantom: core::marker::PhantomData<(Device, Result)>,
}
impl<Device: IoDevice, Result: Copy> Clone for IoctlReqRead<Device, Result> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Result: Copy> Copy for IoctlReqRead<Device, Result> {}
unsafe impl<'a, Device, Result> IoctlReq<'a, Device> for IoctlReqRead<Device, Result>
where
*mut Result: AsRawV,
Result: 'a + Copy,
Device: 'a + IoDevice,
{
type ExtArg = ();
type TempMem = Result;
type RawArg = *mut Result;
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
_: &Self::ExtArg,
temp_mem: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, Self::RawArg) {
(self.request, temp_mem.as_mut_ptr())
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
_: int,
_: &Self::ExtArg,
temp_mem: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
unsafe { temp_mem.assume_init() }
}
}
#[repr(transparent)]
pub struct IoctlReqWriteVal<Device: IoDevice, Arg, Result = int>
where
Arg: AsRawV,
{
request: ulong,
_phantom: core::marker::PhantomData<(Device, Arg, Result)>,
}
impl<Device: IoDevice, Arg: AsRawV, Result> Clone for IoctlReqWriteVal<Device, Arg, Result> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Arg: AsRawV, Result> Copy for IoctlReqWriteVal<Device, Arg, Result> {}
unsafe impl<'a, Device, Arg, Result> IoctlReq<'a, Device> for IoctlReqWriteVal<Device, Arg, Result>
where
Arg: 'a + AsRawV,
Result: 'a + FromIoctlResult<int>,
Device: 'a + IoDevice,
{
type ExtArg = Arg;
type TempMem = ();
type RawArg = Arg;
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
arg: &Self::ExtArg,
_: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, Arg) {
(self.request, *arg)
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
ret: int,
_: &Self::ExtArg,
_: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
Result::from_ioctl_result(&ret)
}
}
#[repr(transparent)]
pub struct IoctlReqWrite<Device: IoDevice, Arg, Result = int>
where
*const Arg: AsRawV,
{
request: ulong,
_phantom: core::marker::PhantomData<(Device, Arg, Result)>,
}
impl<Device: IoDevice, Arg, Result> Clone for IoctlReqWrite<Device, Arg, Result> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Arg, Result> Copy for IoctlReqWrite<Device, Arg, Result> {}
unsafe impl<'a, Device, Arg, Result> IoctlReq<'a, Device> for IoctlReqWrite<Device, Arg, Result>
where
*const Arg: AsRawV,
Arg: 'a,
Result: 'a + FromIoctlResult<int>,
Device: 'a + IoDevice,
{
type ExtArg = &'a Arg;
type TempMem = ();
type RawArg = *const Arg;
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
arg: &Self::ExtArg,
_: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, *const Arg) {
(self.request, (*arg) as *const Arg)
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
ret: int,
_: &Self::ExtArg,
_: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
Result::from_ioctl_result(&ret)
}
}
#[repr(transparent)]
pub struct IoctlReqWriteRead<Device: IoDevice, Arg, Result = int>
where
*const Arg: AsRawV,
{
request: ulong,
_phantom: core::marker::PhantomData<(Device, Arg, Result)>,
}
impl<Device: IoDevice, Arg, Result> Clone for IoctlReqWriteRead<Device, Arg, Result> {
fn clone(&self) -> Self {
Self {
request: self.request,
_phantom: core::marker::PhantomData,
}
}
}
impl<Device: IoDevice, Arg, Result> Copy for IoctlReqWriteRead<Device, Arg, Result> {}
unsafe impl<'a, Device, Arg, Result> IoctlReq<'a, Device> for IoctlReqWriteRead<Device, Arg, Result>
where
Device: IoDevice + 'a,
*const Arg: AsRawV,
Arg: 'a,
Result: 'a + FromIoctlResult<int>,
{
type ExtArg = &'a mut Arg;
type TempMem = ();
type RawArg = *mut Arg;
type Result = Result;
#[inline(always)]
fn prepare_ioctl_args(
&self,
arg: &Self::ExtArg,
_: &mut MaybeUninit<Self::TempMem>,
) -> (ulong, *mut Arg) {
(self.request, (*arg) as *const Arg as *mut Arg)
}
#[inline(always)]
fn prepare_ioctl_result(
&self,
ret: int,
_: &Self::ExtArg,
_: &MaybeUninit<Self::TempMem>,
) -> Self::Result {
Result::from_ioctl_result(&ret)
}
}
pub trait FromIoctlResult<Raw> {
fn from_ioctl_result(raw: &Raw) -> Self;
}
impl FromIoctlResult<int> for int {
fn from_ioctl_result(raw: &int) -> Self {
*raw
}
}
impl<Device: IoDevice> FromIoctlResult<int> for super::File<Device> {
fn from_ioctl_result(raw: &int) -> Self {
unsafe { super::File::from_raw_fd(*raw) }
}
}
#[allow(non_snake_case)]
const fn _IOC(dir: ulong, typ: ulong, nr: ulong, size: ulong) -> ulong {
(dir << 30) | (typ << 8) | (nr << 0) | (size << 16)
}
#[allow(non_snake_case)]
pub const fn _IO(typ: ulong, nr: ulong) -> ulong {
_IOC(0, typ, nr, 0)
}
#[allow(non_snake_case)]
pub const fn _IOR(typ: ulong, nr: ulong, size: ulong) -> ulong {
_IOC(2, typ, nr, size)
}
#[allow(non_snake_case)]
pub const fn _IOW(typ: ulong, nr: ulong, size: ulong) -> ulong {
_IOC(1, typ, nr, size)
}
#[allow(non_snake_case)]
pub const fn _IOWR(typ: ulong, nr: ulong, size: ulong) -> ulong {
_IOC(1 | 2, typ, nr, size)
}