use std::os::raw::c_char;
use wpilib_sys::*;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum Port {
Onboard = HAL_SerialPort::Onboard,
MXP = HAL_SerialPort::MXP,
USB1 = HAL_SerialPort::USB1,
USB2 = HAL_SerialPort::USB2,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Parity {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum StopBits {
One = 10,
OnePointFive = 15,
Two = 20,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum WriteBufferMode {
FlushOnAcces = 1,
FlushWhenFull = 2,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum FlowControl {
None = 0,
XonXoff = 1,
RtsCts = 2,
DtrDsr = 4,
}
#[derive(Debug)]
pub struct SerialPort {
port: Port,
}
impl SerialPort {
#[allow(clippy::new_ret_no_self)]
pub fn new(
baud_rate: u32,
port: Port,
databits: u32,
parity: Parity,
stopbits: StopBits,
) -> HalResult<Self> {
hal_call!(HAL_InitializeSerialPort(port as HAL_SerialPort::Type))?;
hal_call!(HAL_SetSerialBaudRate(
port as HAL_SerialPort::Type,
baud_rate as i32
))?;
hal_call!(HAL_SetSerialDataBits(
port as HAL_SerialPort::Type,
databits as i32
))?;
hal_call!(HAL_SetSerialParity(
port as HAL_SerialPort::Type,
parity as i32
))?;
hal_call!(HAL_SetSerialStopBits(
port as HAL_SerialPort::Type,
stopbits as i32
))?;
let mut serial_port = SerialPort { port };
serial_port.set_timeout(5.0)?;
serial_port.set_write_buf_mode(WriteBufferMode::FlushOnAcces)?;
serial_port.enable_termination(b'\n')?;
report_usage(usage::resource_types::SerialPort, 0);
Ok(serial_port)
}
pub fn set_flow_control(&mut self, flow_control: FlowControl) -> HalResult<()> {
hal_call!(HAL_SetSerialFlowControl(
self.port as HAL_SerialPort::Type,
flow_control as i32
))
}
#[allow(clippy::unnecessary_cast)]
pub fn enable_termination(&mut self, terminator: u8) -> HalResult<()> {
hal_call!(HAL_EnableSerialTermination(
self.port as HAL_SerialPort::Type,
terminator as c_char
))
}
pub fn disable_termination(&mut self) -> HalResult<()> {
hal_call!(HAL_DisableSerialTermination(
self.port as HAL_SerialPort::Type
))
}
pub fn bytes_received(&mut self) -> HalResult<i32> {
hal_call!(HAL_GetSerialBytesReceived(
self.port as HAL_SerialPort::Type
))
}
#[allow(clippy::unnecessary_cast)]
pub fn read(&mut self, buf: &mut [u8]) -> HalResult<i32> {
hal_call!(HAL_ReadSerial(
self.port as HAL_SerialPort::Type,
buf.as_mut_ptr() as *mut c_char,
buf.len() as i32
))
}
#[allow(clippy::unnecessary_cast)]
pub fn read_len(&mut self, buf: &mut [u8], len: usize) -> HalResult<i32> {
let len = len.min(buf.len());
hal_call!(HAL_ReadSerial(
self.port as HAL_SerialPort::Type,
buf.as_mut_ptr() as *mut c_char,
len as i32
))
}
pub fn write(&mut self, buf: &[u8]) -> HalResult<i32> {
hal_call!(HAL_WriteSerial(
self.port as HAL_SerialPort::Type,
buf.as_ptr() as *const c_char,
buf.len() as i32
))
}
pub fn set_timeout(&mut self, seconds: f64) -> HalResult<()> {
hal_call!(HAL_SetSerialTimeout(
self.port as HAL_SerialPort::Type,
seconds
))
}
pub fn set_read_buf_size(&mut self, size: u32) -> HalResult<()> {
hal_call!(HAL_SetSerialReadBufferSize(
self.port as HAL_SerialPort::Type,
size as i32
))
}
pub fn set_write_buf_size(&mut self, size: u32) -> HalResult<()> {
hal_call!(HAL_SetSerialWriteBufferSize(
self.port as HAL_SerialPort::Type,
size as i32
))
}
pub fn set_write_buf_mode(&mut self, mode: WriteBufferMode) -> HalResult<()> {
hal_call!(HAL_SetSerialWriteMode(
self.port as HAL_SerialPort::Type,
mode as i32
))
}
pub fn flush(&mut self) -> HalResult<()> {
hal_call!(HAL_FlushSerial(self.port as HAL_SerialPort::Type))
}
pub fn reset(&mut self) -> HalResult<()> {
hal_call!(HAL_ClearSerial(self.port as HAL_SerialPort::Type))
}
}
use std::io;
impl io::Write for SerialPort {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
hal_to_io_len(self.write(buf))
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
hal_to_io(self.flush())
}
}
impl io::Read for SerialPort {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
hal_to_io_len(self.read(buf))
}
}
#[inline]
fn hal_to_io_len(r: HalResult<i32>) -> io::Result<usize> {
match r {
Ok(x) => Ok(x as usize),
Err(t) => Err(io::Error::new(io::ErrorKind::Other, t)),
}
}
#[inline]
fn hal_to_io<T>(r: HalResult<T>) -> io::Result<T> {
match r {
Ok(x) => Ok(x),
Err(t) => Err(io::Error::new(io::ErrorKind::Other, t)),
}
}
impl Drop for SerialPort {
fn drop(&mut self) {
hal_call!(HAL_CloseSerial(self.port as HAL_SerialPort::Type)).ok();
}
}