2018-05-15 21:27:23 +08:00
|
|
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError};
|
|
|
|
|
|
|
|
#[derive(Fail, Debug)]
|
|
|
|
pub enum Error<T> {
|
|
|
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
|
|
|
UnknownPacket(u8),
|
|
|
|
#[fail(display = "{}", _0)]
|
|
|
|
Io(#[cause] IoError<T>)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<IoError<T>> for Error<T> {
|
|
|
|
fn from(value: IoError<T>) -> Error<T> {
|
|
|
|
Error::Io(value)
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 18:02:39 +08:00
|
|
|
|
2017-02-21 21:55:36 +08:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Packet {
|
|
|
|
EchoRequest,
|
|
|
|
EchoReply,
|
2018-02-20 18:48:54 +08:00
|
|
|
ResetRequest { phy: bool },
|
|
|
|
ResetAck,
|
2017-04-02 23:45:55 +08:00
|
|
|
|
|
|
|
RtioErrorRequest,
|
|
|
|
RtioNoErrorReply,
|
2017-09-29 16:32:57 +08:00
|
|
|
RtioErrorSequenceErrorReply { channel: u16 },
|
|
|
|
RtioErrorCollisionReply { channel: u16 },
|
|
|
|
RtioErrorBusyReply { channel: u16 },
|
2017-04-02 23:45:55 +08:00
|
|
|
|
2017-02-23 16:23:51 +08:00
|
|
|
MonitorRequest { channel: u16, probe: u8 },
|
|
|
|
MonitorReply { value: u32 },
|
|
|
|
InjectionRequest { channel: u16, overrd: u8, value: u8 },
|
|
|
|
InjectionStatusRequest { channel: u16, overrd: u8 },
|
2017-06-21 14:07:16 +08:00
|
|
|
InjectionStatusReply { value: u8 },
|
|
|
|
|
|
|
|
I2cStartRequest { busno: u8 },
|
|
|
|
I2cRestartRequest { busno: u8 },
|
|
|
|
I2cStopRequest { busno: u8 },
|
|
|
|
I2cWriteRequest { busno: u8, data: u8 },
|
|
|
|
I2cWriteReply { succeeded: bool, ack: bool },
|
|
|
|
I2cReadRequest { busno: u8, ack: bool },
|
|
|
|
I2cReadReply { succeeded: bool, data: u8 },
|
|
|
|
I2cBasicReply { succeeded: bool },
|
|
|
|
|
2018-02-23 17:50:49 +08:00
|
|
|
SpiSetConfigRequest { busno: u8, flags: u8, length: u8, div: u8, cs: u8 },
|
2017-06-21 14:07:16 +08:00
|
|
|
SpiWriteRequest { busno: u8, data: u32 },
|
|
|
|
SpiReadRequest { busno: u8 },
|
|
|
|
SpiReadReply { succeeded: bool, data: u32 },
|
|
|
|
SpiBasicReply { succeeded: bool },
|
2017-02-21 21:55:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Packet {
|
2018-05-15 21:27:23 +08:00
|
|
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
|
|
|
where R: Read + ?Sized
|
|
|
|
{
|
2018-05-14 18:02:39 +08:00
|
|
|
Ok(match reader.read_u8()? {
|
2017-04-02 23:45:55 +08:00
|
|
|
0x00 => Packet::EchoRequest,
|
|
|
|
0x01 => Packet::EchoReply,
|
2018-02-20 18:48:54 +08:00
|
|
|
0x02 => Packet::ResetRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
phy: reader.read_bool()?
|
2018-02-20 18:48:54 +08:00
|
|
|
},
|
|
|
|
0x03 => Packet::ResetAck,
|
2017-04-02 23:45:55 +08:00
|
|
|
|
|
|
|
0x20 => Packet::RtioErrorRequest,
|
|
|
|
0x21 => Packet::RtioNoErrorReply,
|
2017-09-29 16:32:57 +08:00
|
|
|
0x22 => Packet::RtioErrorSequenceErrorReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
|
|
|
0x23 => Packet::RtioErrorCollisionReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
|
|
|
0x24 => Packet::RtioErrorBusyReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
|
|
|
|
0x40 => Packet::MonitorRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?,
|
|
|
|
probe: reader.read_u8()?
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
0x41 => Packet::MonitorReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
value: reader.read_u32()?
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
0x50 => Packet::InjectionRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?,
|
|
|
|
overrd: reader.read_u8()?,
|
|
|
|
value: reader.read_u8()?
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
0x51 => Packet::InjectionStatusRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
channel: reader.read_u16()?,
|
|
|
|
overrd: reader.read_u8()?
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
0x52 => Packet::InjectionStatusReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
value: reader.read_u8()?
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
2017-06-21 14:07:16 +08:00
|
|
|
|
|
|
|
0x80 => Packet::I2cStartRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x81 => Packet::I2cRestartRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x82 => Packet::I2cStopRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x83 => Packet::I2cWriteRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?,
|
|
|
|
data: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x84 => Packet::I2cWriteReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
succeeded: reader.read_bool()?,
|
|
|
|
ack: reader.read_bool()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x85 => Packet::I2cReadRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?,
|
|
|
|
ack: reader.read_bool()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x86 => Packet::I2cReadReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
succeeded: reader.read_bool()?,
|
|
|
|
data: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x87 => Packet::I2cBasicReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
succeeded: reader.read_bool()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
0x90 => Packet::SpiSetConfigRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?,
|
|
|
|
flags: reader.read_u8()?,
|
|
|
|
length: reader.read_u8()?,
|
|
|
|
div: reader.read_u8()?,
|
|
|
|
cs: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
2018-02-23 17:50:49 +08:00
|
|
|
/* 0x91: was Packet::SpiSetXferRequest */
|
2017-06-21 14:07:16 +08:00
|
|
|
0x92 => Packet::SpiWriteRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?,
|
|
|
|
data: reader.read_u32()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x93 => Packet::SpiReadRequest {
|
2018-05-14 18:02:39 +08:00
|
|
|
busno: reader.read_u8()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x94 => Packet::SpiReadReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
succeeded: reader.read_bool()?,
|
|
|
|
data: reader.read_u32()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
0x95 => Packet::SpiBasicReply {
|
2018-05-14 18:02:39 +08:00
|
|
|
succeeded: reader.read_bool()?
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
|
2018-05-15 21:27:23 +08:00
|
|
|
ty => return Err(Error::UnknownPacket(ty))
|
2017-02-21 21:55:36 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:27:23 +08:00
|
|
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
|
|
|
where W: Write + ?Sized
|
|
|
|
{
|
2017-02-21 21:55:36 +08:00
|
|
|
match *self {
|
2018-05-14 18:02:39 +08:00
|
|
|
Packet::EchoRequest =>
|
|
|
|
writer.write_u8(0x00)?,
|
|
|
|
Packet::EchoReply =>
|
|
|
|
writer.write_u8(0x01)?,
|
2018-02-20 18:48:54 +08:00
|
|
|
Packet::ResetRequest { phy } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x02)?;
|
|
|
|
writer.write_bool(phy)?;
|
2018-02-20 18:48:54 +08:00
|
|
|
},
|
2018-05-14 18:02:39 +08:00
|
|
|
Packet::ResetAck =>
|
|
|
|
writer.write_u8(0x03)?,
|
2017-04-02 23:45:55 +08:00
|
|
|
|
2018-05-14 18:02:39 +08:00
|
|
|
Packet::RtioErrorRequest =>
|
|
|
|
writer.write_u8(0x20)?,
|
|
|
|
Packet::RtioNoErrorReply =>
|
|
|
|
writer.write_u8(0x21)?,
|
2017-09-29 16:32:57 +08:00
|
|
|
Packet::RtioErrorSequenceErrorReply { channel } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x22)?;
|
|
|
|
writer.write_u16(channel)?;
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
|
|
|
Packet::RtioErrorCollisionReply { channel } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x23)?;
|
|
|
|
writer.write_u16(channel)?;
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
|
|
|
Packet::RtioErrorBusyReply { channel } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x24)?;
|
|
|
|
writer.write_u16(channel)?;
|
2017-09-29 16:32:57 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
|
2017-02-23 16:23:51 +08:00
|
|
|
Packet::MonitorRequest { channel, probe } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x40)?;
|
|
|
|
writer.write_u16(channel)?;
|
|
|
|
writer.write_u8(probe)?;
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
|
|
|
Packet::MonitorReply { value } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x41)?;
|
|
|
|
writer.write_u32(value)?;
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
|
|
|
Packet::InjectionRequest { channel, overrd, value } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x50)?;
|
|
|
|
writer.write_u16(channel)?;
|
|
|
|
writer.write_u8(overrd)?;
|
|
|
|
writer.write_u8(value)?;
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
|
|
|
Packet::InjectionStatusRequest { channel, overrd } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x51)?;
|
|
|
|
writer.write_u16(channel)?;
|
|
|
|
writer.write_u8(overrd)?;
|
2017-02-23 16:23:51 +08:00
|
|
|
},
|
|
|
|
Packet::InjectionStatusReply { value } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x52)?;
|
|
|
|
writer.write_u8(value)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
Packet::I2cStartRequest { busno } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x80)?;
|
|
|
|
writer.write_u8(busno)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cRestartRequest { busno } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x81)?;
|
|
|
|
writer.write_u8(busno)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cStopRequest { busno } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x82)?;
|
|
|
|
writer.write_u8(busno)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cWriteRequest { busno, data } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x83)?;
|
|
|
|
writer.write_u8(busno)?;
|
|
|
|
writer.write_u8(data)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cWriteReply { succeeded, ack } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x84)?;
|
|
|
|
writer.write_bool(succeeded)?;
|
|
|
|
writer.write_bool(ack)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cReadRequest { busno, ack } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x85)?;
|
|
|
|
writer.write_u8(busno)?;
|
|
|
|
writer.write_bool(ack)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cReadReply { succeeded, data } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x86)?;
|
|
|
|
writer.write_bool(succeeded)?;
|
|
|
|
writer.write_u8(data)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::I2cBasicReply { succeeded } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x87)?;
|
|
|
|
writer.write_bool(succeeded)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
|
2018-02-23 17:50:49 +08:00
|
|
|
Packet::SpiSetConfigRequest { busno, flags, length, div, cs } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x90)?;
|
|
|
|
writer.write_u8(busno)?;
|
|
|
|
writer.write_u8(flags)?;
|
|
|
|
writer.write_u8(length)?;
|
|
|
|
writer.write_u8(div)?;
|
|
|
|
writer.write_u8(cs)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::SpiWriteRequest { busno, data } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x92)?;
|
|
|
|
writer.write_u8(busno)?;
|
|
|
|
writer.write_u32(data)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::SpiReadRequest { busno } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x93)?;
|
|
|
|
writer.write_u8(busno)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::SpiReadReply { succeeded, data } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x94)?;
|
|
|
|
writer.write_bool(succeeded)?;
|
|
|
|
writer.write_u32(data)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
|
|
|
Packet::SpiBasicReply { succeeded } => {
|
2018-05-14 18:02:39 +08:00
|
|
|
writer.write_u8(0x95)?;
|
|
|
|
writer.write_bool(succeeded)?;
|
2017-06-21 14:07:16 +08:00
|
|
|
},
|
2017-02-21 21:55:36 +08:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|