#![allow(dead_code)]
use std::io;
use std::mem;
use std::result;
use libc::{self, c_int, ioctl};
use super::segment::Segment;
#[cfg(target_env = "gnu")]
type IoctlLong = libc::c_ulong;
#[cfg(target_env = "musl")]
type IoctlLong = c_int;
pub type Result<T> = result::Result<T, io::Error>;
const NRBITS: u8 = 8;
const TYPEBITS: u8 = 8;
const SIZEBITS: u8 = 14;
const DIRBITS: u8 = 2;
const NRSHIFT: u8 = 0;
const TYPESHIFT: u8 = NRSHIFT + NRBITS;
const SIZESHIFT: u8 = TYPESHIFT + TYPEBITS;
const DIRSHIFT: u8 = SIZESHIFT + SIZEBITS;
const NR_MESSAGE: IoctlLong = 0 << NRSHIFT;
const NR_MODE: IoctlLong = 1 << NRSHIFT;
const NR_LSB_FIRST: IoctlLong = 2 << NRSHIFT;
const NR_BITS_PER_WORD: IoctlLong = 3 << NRSHIFT;
const NR_MAX_SPEED_HZ: IoctlLong = 4 << NRSHIFT;
const NR_MODE32: IoctlLong = 5 << NRSHIFT;
const TYPE_SPI: IoctlLong = (b'k' as IoctlLong) << TYPESHIFT;
const SIZE_U8: IoctlLong = (mem::size_of::<u8>() as IoctlLong) << SIZESHIFT;
const SIZE_U32: IoctlLong = (mem::size_of::<u32>() as IoctlLong) << SIZESHIFT;
const DIR_NONE: IoctlLong = 0;
const DIR_WRITE: IoctlLong = 1 << DIRSHIFT;
const DIR_READ: IoctlLong = 2 << DIRSHIFT;
const REQ_RD_MODE: IoctlLong = DIR_READ | TYPE_SPI | NR_MODE | SIZE_U8;
const REQ_RD_LSB_FIRST: IoctlLong = DIR_READ | TYPE_SPI | NR_LSB_FIRST | SIZE_U8;
const REQ_RD_BITS_PER_WORD: IoctlLong = DIR_READ | TYPE_SPI | NR_BITS_PER_WORD | SIZE_U8;
const REQ_RD_MAX_SPEED_HZ: IoctlLong = DIR_READ | TYPE_SPI | NR_MAX_SPEED_HZ | SIZE_U32;
const REQ_RD_MODE_32: IoctlLong = DIR_READ | TYPE_SPI | NR_MODE32 | SIZE_U32;
const REQ_WR_MESSAGE: IoctlLong = DIR_WRITE | TYPE_SPI | NR_MESSAGE;
const REQ_WR_MODE: IoctlLong = DIR_WRITE | TYPE_SPI | NR_MODE | SIZE_U8;
const REQ_WR_LSB_FIRST: IoctlLong = DIR_WRITE | TYPE_SPI | NR_LSB_FIRST | SIZE_U8;
const REQ_WR_BITS_PER_WORD: IoctlLong = DIR_WRITE | TYPE_SPI | NR_BITS_PER_WORD | SIZE_U8;
const REQ_WR_MAX_SPEED_HZ: IoctlLong = DIR_WRITE | TYPE_SPI | NR_MAX_SPEED_HZ | SIZE_U32;
const REQ_WR_MODE_32: IoctlLong = DIR_WRITE | TYPE_SPI | NR_MODE32 | SIZE_U32;
pub const MODE_CPHA: u8 = 0x01;
pub const MODE_CPOL: u8 = 0x02;
pub const MODE_0: u8 = 0;
pub const MODE_1: u8 = MODE_CPHA;
pub const MODE_2: u8 = MODE_CPOL;
pub const MODE_3: u8 = MODE_CPOL | MODE_CPHA;
pub const MODE_CS_HIGH: u8 = 0x04;
pub const MODE_LSB_FIRST: u8 = 0x08; pub const MODE_3WIRE: u8 = 0x10; pub const MODE_LOOP: u8 = 0x20; pub const MODE_NO_CS: u8 = 0x40; pub const MODE_READY: u8 = 0x80; pub const MODE_TX_DUAL: u32 = 0x0100; pub const MODE_TX_QUAD: u32 = 0x0200; pub const MODE_RX_DUAL: u32 = 0x0400; pub const MODE_RX_QUAD: u32 = 0x0800; pub fn mode(fd: c_int, value: &mut u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_RD_MODE, value) })
}
pub fn set_mode(fd: c_int, value: u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_WR_MODE, &value) })
}
pub fn lsb_first(fd: c_int, value: &mut u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_RD_LSB_FIRST, value) })
}
pub fn set_lsb_first(fd: c_int, value: u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_WR_LSB_FIRST, &value) })
}
pub fn bits_per_word(fd: c_int, value: &mut u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_RD_BITS_PER_WORD, value) })
}
pub fn set_bits_per_word(fd: c_int, value: u8) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_WR_BITS_PER_WORD, &value) })
}
pub fn clock_speed(fd: c_int, value: &mut u32) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_RD_MAX_SPEED_HZ, value) })
}
pub fn set_clock_speed(fd: c_int, value: u32) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_WR_MAX_SPEED_HZ, &value) })
}
pub fn mode32(fd: c_int, value: &mut u32) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_RD_MODE_32, value) })
}
pub fn set_mode32(fd: c_int, value: u32) -> Result<i32> {
parse_retval!(unsafe { ioctl(fd, REQ_WR_MODE_32, &value) })
}
pub fn transfer(fd: c_int, segments: &[Segment<'_, '_>]) -> Result<i32> {
parse_retval!(unsafe {
ioctl(
fd,
REQ_WR_MESSAGE | ((std::mem::size_of_val(segments) as IoctlLong) << SIZESHIFT),
segments,
)
})
}