use std::os::unix::io::RawFd;
use bitflags::bitflags;
use nix::libc;
use crate::Result;
mod raw {
use nix::libc;
use nix::{ioctl_none_bad, ioctl_read, ioctl_read_bad, ioctl_write_ptr, ioctl_write_ptr_bad};
ioctl_none_bad!(tiocexcl, libc::TIOCEXCL);
ioctl_none_bad!(tiocnxcl, libc::TIOCNXCL);
ioctl_read_bad!(tiocmget, libc::TIOCMGET, libc::c_int);
ioctl_none_bad!(tiocsbrk, libc::TIOCSBRK);
ioctl_none_bad!(tioccbrk, libc::TIOCCBRK);
#[cfg(any(target_os = "android", target_os = "linux"))]
ioctl_read_bad!(fionread, libc::FIONREAD, libc::c_int);
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
ioctl_read!(fionread, b'f', 127, libc::c_int);
#[cfg(any(target_os = "android", target_os = "linux"))]
ioctl_read_bad!(tiocoutq, libc::TIOCOUTQ, libc::c_int);
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
ioctl_read!(tiocoutq, b't', 115, libc::c_int);
ioctl_write_ptr_bad!(tiocmbic, libc::TIOCMBIC, libc::c_int);
ioctl_write_ptr_bad!(tiocmbis, libc::TIOCMBIS, libc::c_int);
ioctl_read!(
#[cfg(any(
target_os = "android",
all(
target_os = "linux",
not(any(
target_env = "musl",
target_arch = "powerpc",
target_arch = "powerpc64"
))
)
))]
tcgets2,
b'T',
0x2A,
libc::termios2
);
ioctl_write_ptr!(
#[cfg(any(
target_os = "android",
all(
target_os = "linux",
not(any(
target_env = "musl",
target_arch = "powerpc",
target_arch = "powerpc64"
))
)
))]
tcsets2,
b'T',
0x2B,
libc::termios2
);
#[cfg(any(target_os = "ios", target_os = "macos"))]
const IOSSIOSPEED: libc::c_ulong = 0x80045402;
ioctl_write_ptr_bad!(
#[cfg(any(target_os = "ios", target_os = "macos"))]
iossiospeed,
IOSSIOSPEED,
libc::speed_t
);
}
bitflags! {
pub struct SerialLines: libc::c_int {
const DATA_SET_READY = libc::TIOCM_DSR;
const DATA_TERMINAL_READY = libc::TIOCM_DTR;
const REQUEST_TO_SEND = libc::TIOCM_RTS;
const SECONDARY_TRANSMIT = libc::TIOCM_ST;
const SECONDARY_RECEIVE = libc::TIOCM_SR;
const CLEAR_TO_SEND = libc::TIOCM_CTS;
const DATA_CARRIER_DETECT = libc::TIOCM_CAR;
const RING = libc::TIOCM_RNG;
}
}
pub fn tiocexcl(fd: RawFd) -> Result<()> {
unsafe { raw::tiocexcl(fd) }
.map(|_| ())
.map_err(|e| e.into())
}
pub fn tiocnxcl(fd: RawFd) -> Result<()> {
unsafe { raw::tiocnxcl(fd) }
.map(|_| ())
.map_err(|e| e.into())
}
pub fn tiocmget(fd: RawFd) -> Result<SerialLines> {
let mut status: libc::c_int = 0;
unsafe { raw::tiocmget(fd, &mut status) }
.map(|_| SerialLines::from_bits_truncate(status))
.map_err(|e| e.into())
}
pub fn tiocsbrk(fd: RawFd) -> Result<()> {
unsafe { raw::tiocsbrk(fd) }
.map(|_| ())
.map_err(|e| e.into())
}
pub fn tioccbrk(fd: RawFd) -> Result<()> {
unsafe { raw::tioccbrk(fd) }
.map(|_| ())
.map_err(|e| e.into())
}
pub fn fionread(fd: RawFd) -> Result<u32> {
let mut retval: libc::c_int = 0;
unsafe { raw::fionread(fd, &mut retval) }
.map(|_| retval as u32)
.map_err(|e| e.into())
}
pub fn tiocoutq(fd: RawFd) -> Result<u32> {
let mut retval: libc::c_int = 0;
unsafe { raw::tiocoutq(fd, &mut retval) }
.map(|_| retval as u32)
.map_err(|e| e.into())
}
pub fn tiocmbic(fd: RawFd, status: SerialLines) -> Result<()> {
let bits = status.bits() as libc::c_int;
unsafe { raw::tiocmbic(fd, &bits) }
.map(|_| ())
.map_err(|e| e.into())
}
pub fn tiocmbis(fd: RawFd, status: SerialLines) -> Result<()> {
let bits = status.bits() as libc::c_int;
unsafe { raw::tiocmbis(fd, &bits) }
.map(|_| ())
.map_err(|e| e.into())
}
#[cfg(any(
target_os = "android",
all(
target_os = "linux",
not(any(
target_env = "musl",
target_arch = "powerpc",
target_arch = "powerpc64"
))
)
))]
pub fn tcgets2(fd: RawFd) -> Result<libc::termios2> {
let mut options = std::mem::MaybeUninit::uninit();
match unsafe { raw::tcgets2(fd, options.as_mut_ptr()) } {
Ok(_) => unsafe { Ok(options.assume_init()) },
Err(e) => Err(e.into()),
}
}
#[cfg(any(
target_os = "android",
all(
target_os = "linux",
not(any(
target_env = "musl",
target_arch = "powerpc",
target_arch = "powerpc64"
))
)
))]
pub fn tcsets2(fd: RawFd, options: &libc::termios2) -> Result<()> {
unsafe { raw::tcsets2(fd, options) }
.map(|_| ())
.map_err(|e| e.into())
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub fn iossiospeed(fd: RawFd, baud_rate: &libc::speed_t) -> Result<()> {
unsafe { raw::iossiospeed(fd, baud_rate) }
.map(|_| ())
.map_err(|e| e.into())
}