forked from M-Labs/artiq-zynq
parent
e0560a2db9
commit
d11e3fdad8
@ -23,7 +23,6 @@ mod config;
|
||||
mod net_settings;
|
||||
mod proto_core_io;
|
||||
mod proto_async;
|
||||
mod proto_mgmt;
|
||||
mod comms;
|
||||
mod rpc;
|
||||
#[path = "../../../build/pl.rs"]
|
||||
|
@ -6,9 +6,63 @@ use alloc::rc::Rc;
|
||||
use log::{self, info, warn, LevelFilter};
|
||||
|
||||
use crate::logger::{BufferLogger, LogBufferRef};
|
||||
use crate::proto_async;
|
||||
use crate::proto_mgmt::*;
|
||||
use crate::proto_async::*;
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
NetworkError(smoltcp::Error),
|
||||
UnknownLogLevel(u8),
|
||||
UnexpectedPattern,
|
||||
UnrecognizedPacket,
|
||||
}
|
||||
|
||||
type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
impl core::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match self {
|
||||
&Error::NetworkError(error) => write!(f, "network error: {}", error),
|
||||
&Error::UnknownLogLevel(lvl) => write!(f, "unknown log level {}", lvl),
|
||||
&Error::UnexpectedPattern => write!(f, "unexpected pattern"),
|
||||
&Error::UnrecognizedPacket => write!(f, "unrecognized packet"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<smoltcp::Error> for Error {
|
||||
fn from(error: smoltcp::Error) -> Self {
|
||||
Error::NetworkError(error)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromPrimitive)]
|
||||
pub enum Request {
|
||||
GetLog = 1,
|
||||
ClearLog = 2,
|
||||
PullLog = 7,
|
||||
SetLogFilter = 3,
|
||||
SetUartLogFilter = 6,
|
||||
}
|
||||
|
||||
#[repr(i8)]
|
||||
pub enum Reply {
|
||||
Success = 1,
|
||||
LogContent = 2,
|
||||
}
|
||||
|
||||
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter> {
|
||||
Ok(match read_i8(stream).await? {
|
||||
0 => log::LevelFilter::Off,
|
||||
1 => log::LevelFilter::Error,
|
||||
2 => log::LevelFilter::Warn,
|
||||
3 => log::LevelFilter::Info,
|
||||
4 => log::LevelFilter::Debug,
|
||||
5 => log::LevelFilter::Trace,
|
||||
lv => return Err(Error::UnknownLogLevel(lv as u8)),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_logger_buffer_pred<F>(f: F) -> LogBufferRef<'static>
|
||||
where
|
||||
@ -31,23 +85,27 @@ async fn get_logger_buffer() -> LogBufferRef<'static> {
|
||||
get_logger_buffer_pred(|_| true).await
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) -> Result<(), Error> {
|
||||
Request::read_magic(stream).await?;
|
||||
async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) -> Result<()> {
|
||||
if !expect(&stream, b"ARTIQ management\n").await? {
|
||||
return Err(Error::UnexpectedPattern);
|
||||
}
|
||||
|
||||
loop {
|
||||
let req = Request::read_from(stream).await;
|
||||
if let Err(Error::Io(smoltcp::Error::Illegal)) = req {
|
||||
let msg = read_i8(stream).await;
|
||||
if let Err(smoltcp::Error::Illegal) = msg {
|
||||
return Ok(());
|
||||
}
|
||||
match req? {
|
||||
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
|
||||
match msg {
|
||||
Request::GetLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
Reply::LogContent(buffer.extract()).write_to(stream).await?;
|
||||
write_i8(stream, Reply::LogContent as i8).await?;
|
||||
write_chunk(stream, buffer.extract().as_bytes()).await?;
|
||||
}
|
||||
Request::ClearLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
buffer.clear();
|
||||
Reply::Success.write_to(stream).await?;
|
||||
write_i8(stream, Reply::Success as i8).await?;
|
||||
}
|
||||
Request::PullLog => {
|
||||
let id = {
|
||||
@ -63,7 +121,7 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
|
||||
// abort this connection...
|
||||
break;
|
||||
}
|
||||
proto_async::write_chunk(stream, bytes).await?;
|
||||
write_chunk(stream, bytes).await?;
|
||||
if log::max_level() == LevelFilter::Trace {
|
||||
// Hold exclusive access over the logger until we get positive
|
||||
// acknowledgement; otherwise we get an infinite loop of network
|
||||
@ -77,12 +135,14 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
|
||||
buffer.clear();
|
||||
}
|
||||
},
|
||||
Request::SetLogFilter(lvl) => {
|
||||
Request::SetLogFilter => {
|
||||
let lvl = read_log_level_filter(stream).await?;
|
||||
info!("Changing log level to {}", lvl);
|
||||
log::set_max_level(lvl);
|
||||
Reply::Success.write_to(stream).await?;
|
||||
write_i8(stream, Reply::Success as i8).await?;
|
||||
}
|
||||
Request::SetUartLogFilter(lvl) => {
|
||||
Request::SetUartLogFilter => {
|
||||
let lvl = read_log_level_filter(stream).await?;
|
||||
info!("Changing UART log level to {}", lvl);
|
||||
unsafe {
|
||||
BufferLogger::get_logger()
|
||||
@ -90,7 +150,7 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
|
||||
.unwrap()
|
||||
.set_uart_log_level(lvl);
|
||||
}
|
||||
Reply::Success.write_to(stream).await?;
|
||||
write_i8(stream, Reply::Success as i8).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +0,0 @@
|
||||
use libasync::smoltcp::TcpStream;
|
||||
use libboard_zynq::smoltcp::Error as IoError;
|
||||
use log;
|
||||
|
||||
use crate::proto_async::*;
|
||||
|
||||
pub enum Error {
|
||||
WrongMagic,
|
||||
UnknownPacket(u8),
|
||||
UnknownLogLevel(u8),
|
||||
Io(IoError),
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
use Error::*;
|
||||
match self {
|
||||
WrongMagic => write!(f, "Wrong magic string"),
|
||||
UnknownPacket(v) => write!(f, "Unknown packet {:#02x}", v),
|
||||
UnknownLogLevel(v) => write!(f, "Unknown log level {}", v),
|
||||
Io(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
fn from(value: IoError) -> Error {
|
||||
Error::Io(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Request {
|
||||
GetLog,
|
||||
ClearLog,
|
||||
PullLog,
|
||||
SetLogFilter(log::LevelFilter),
|
||||
SetUartLogFilter(log::LevelFilter),
|
||||
}
|
||||
|
||||
pub enum Reply<'a> {
|
||||
Success,
|
||||
LogContent(&'a str),
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub async fn read_from(stream: &mut TcpStream) -> Result<Self, Error> {
|
||||
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter, Error> {
|
||||
Ok(match read_i8(stream).await? {
|
||||
0 => log::LevelFilter::Off,
|
||||
1 => log::LevelFilter::Error,
|
||||
2 => log::LevelFilter::Warn,
|
||||
3 => log::LevelFilter::Info,
|
||||
4 => log::LevelFilter::Debug,
|
||||
5 => log::LevelFilter::Trace,
|
||||
lv => return Err(Error::UnknownLogLevel(lv as u8)),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(match read_i8(stream).await? {
|
||||
1 => Request::GetLog,
|
||||
2 => Request::ClearLog,
|
||||
7 => Request::PullLog,
|
||||
3 => Request::SetLogFilter(read_log_level_filter(stream).await?),
|
||||
6 => Request::SetUartLogFilter(read_log_level_filter(stream).await?),
|
||||
ty => return Err(Error::UnknownPacket(ty as u8)),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn read_magic(stream: &mut TcpStream) -> Result<(), Error> {
|
||||
if !expect(&stream, b"ARTIQ management\n").await? {
|
||||
return Err(Error::WrongMagic);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reply<'a> {
|
||||
pub async fn write_to(&self, stream: &mut TcpStream) -> Result<(), IoError> {
|
||||
match *self {
|
||||
Reply::Success => {
|
||||
write_i8(stream, 1).await?;
|
||||
}
|
||||
Reply::LogContent(ref log) => {
|
||||
write_i8(stream, 2).await?;
|
||||
write_chunk(stream, log.as_bytes()).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user