use embedded_hal::serial::{Read, Write};
use nb::block;
pub trait LegacyStdio: Send {
fn getchar(&mut self) -> u8;
fn putchar(&mut self, ch: u8);
}
struct EmbeddedHalSerial<T> {
inner: T,
}
impl<T> EmbeddedHalSerial<T> {
fn new(inner: T) -> Self {
Self { inner }
}
}
impl<T: Send> LegacyStdio for EmbeddedHalSerial<T>
where
T: Read<u8> + Write<u8>,
{
fn getchar(&mut self) -> u8 {
block!(self.inner.try_read()).ok().unwrap()
}
fn putchar(&mut self, ch: u8) {
block!(self.inner.try_write(ch)).ok();
block!(self.inner.try_flush()).ok();
}
}
struct Fused<T, R>(T, R);
impl<T, R> LegacyStdio for Fused<T, R>
where
T: Write<u8> + Send + 'static,
R: Read<u8> + Send + 'static,
{
fn getchar(&mut self) -> u8 {
block!(self.1.try_read()).ok().unwrap()
}
fn putchar(&mut self, ch: u8) {
block!(self.0.try_write(ch)).ok();
block!(self.0.try_flush()).ok();
}
}
use alloc::boxed::Box;
use spin::Mutex;
lazy_static::lazy_static! {
static ref LEGACY_STDIO: Mutex<Option<Box<dyn LegacyStdio>>> =
Mutex::new(None);
}
#[doc(hidden)] pub fn init_legacy_stdio_embedded_hal<T: Read<u8> + Write<u8> + Send + 'static>(serial: T) {
let serial = EmbeddedHalSerial::new(serial);
*LEGACY_STDIO.lock() = Some(Box::new(serial));
}
#[doc(hidden)] pub fn init_legacy_stdio_embedded_hal_fuse<T, R>(tx: T, rx: R)
where
T: Write<u8> + Send + 'static,
R: Read<u8> + Send + 'static,
{
let serial = Fused(tx, rx);
*LEGACY_STDIO.lock() = Some(Box::new(serial));
}
pub(crate) fn legacy_stdio_putchar(ch: u8) {
if let Some(stdio) = LEGACY_STDIO.lock().as_mut() {
stdio.putchar(ch)
}
}
pub(crate) fn legacy_stdio_getchar() -> u8 {
if let Some(stdio) = LEGACY_STDIO.lock().as_mut() {
stdio.getchar()
} else {
0 }
}
use core::fmt;
struct Stdout;
impl fmt::Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
if let Some(stdio) = LEGACY_STDIO.lock().as_mut() {
for byte in s.as_bytes() {
stdio.putchar(*byte)
}
}
Ok(())
}
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
use fmt::Write;
Stdout.write_fmt(args).unwrap();
}
#[macro_export(local_inner_macros)]
macro_rules! print {
($($arg:tt)*) => ({
$crate::legacy_stdio::_print(core::format_args!($($arg)*));
});
}
#[macro_export(local_inner_macros)]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::legacy_stdio::_print(core::format_args!(core::concat!($fmt, "\n") $(, $($arg)+)?));
}
}