use core::{
marker::PhantomData,
mem,
};
use crate::{
ioctl,
AsRawFd,
};
#[repr(u8)]
pub enum Direction {
None = 0b00,
Write = 0b01,
Read = 0b10,
ReadWrite = 0b11,
}
pub const fn cmd(dir: Direction, ty: u8, nr: u8, size: usize) -> u32 {
if size >> 14 != 0 {
panic!("size must not exceed 14 bits");
}
(nr as u32) | ((ty as u32) << 8) | ((size as u32) << 16) | ((dir as u32) << 30)
}
pub struct None {
cmd: u32,
}
impl None {
pub const fn new(ty: u8, nr: u8) -> Self {
Self {
cmd: cmd(Direction::None, ty, nr, 0),
}
}
pub const fn cmd(&self) -> u32 {
self.cmd
}
#[inline]
pub unsafe fn call(&self, fd: &impl AsRawFd) -> crate::Result<i32> {
ioctl(fd, self.cmd, 0)
}
}
pub struct Read<T> {
cmd: u32,
_marker: PhantomData<*mut T>,
}
impl<T> Read<T> {
pub const fn new(ty: u8, nr: u8) -> Self {
Self {
cmd: cmd(Direction::Read, ty, nr, mem::size_of::<T>()),
_marker: PhantomData,
}
}
pub const fn cmd(&self) -> u32 {
self.cmd
}
#[inline]
pub unsafe fn call(&self, fd: &impl AsRawFd, t: &mut T) -> crate::Result<i32> {
ioctl(fd, self.cmd, t as *mut T as usize)
}
}
pub struct Write<T> {
cmd: u32,
_marker: PhantomData<*const T>,
}
impl<T> Write<T> {
pub const fn new(ty: u8, nr: u8) -> Self {
Self {
cmd: cmd(Direction::Write, ty, nr, mem::size_of::<T>()),
_marker: PhantomData,
}
}
pub const fn cmd(&self) -> u32 {
self.cmd
}
#[inline]
pub unsafe fn call(&self, fd: &impl AsRawFd, t: &T) -> crate::Result<i32> {
ioctl(fd, self.cmd, t as *const T as usize)
}
}
pub struct ReadWrite<T> {
cmd: u32,
_marker: PhantomData<*mut T>,
}
impl<T> ReadWrite<T> {
pub const fn new(ty: u8, nr: u8) -> Self {
Self {
cmd: cmd(Direction::ReadWrite, ty, nr, mem::size_of::<T>()),
_marker: PhantomData,
}
}
pub const fn cmd(&self) -> u32 {
self.cmd
}
#[inline]
pub unsafe fn call(&self, fd: &impl AsRawFd, t: &mut T) -> crate::Result<i32> {
ioctl(fd, self.cmd, t as *mut T as usize)
}
}