1use crate::clock::Clock;
9use crate::command::{Command, CommandCode};
10use crate::error::Error;
11use crate::packet::{Address, ControlByte, CtrlFlags, PacketBuilder, ParsedPacket, Sqn};
12use crate::reply::Reply;
13use crate::transport::Transport;
14use alloc::vec::Vec;
15
16pub trait PdHandler {
19 fn on_command(&mut self, command: &Command) -> Reply;
21}
22
23pub struct Pd<T: Transport, C: Clock, H: PdHandler> {
25 transport: T,
26 #[allow(dead_code)]
27 clock: C,
28 pub address: u8,
30 pub use_crc: bool,
32 handler: H,
33 rx_buf: Vec<u8>,
34 last_sqn: Option<u8>,
36 last_reply: Option<Vec<u8>>,
38}
39
40impl<T: Transport, C: Clock, H: PdHandler> Pd<T, C, H> {
41 pub fn new(transport: T, clock: C, address: u8, handler: H) -> Self {
43 Self {
44 transport,
45 clock,
46 address,
47 use_crc: true,
48 handler,
49 rx_buf: Vec::with_capacity(crate::MAX_BUS_PACKET),
50 last_sqn: None,
51 last_reply: None,
52 }
53 }
54
55 pub fn transport(&mut self) -> &mut T {
57 &mut self.transport
58 }
59
60 pub fn poll_once(&mut self) -> Result<bool, Error> {
66 let mut tmp = [0u8; 64];
67 let n = self.transport.read(&mut tmp)?;
68 if n > 0 {
69 self.rx_buf.extend_from_slice(&tmp[..n]);
70 }
71
72 while let Some(som_pos) = self.rx_buf.iter().position(|&b| b == crate::SOM) {
73 self.rx_buf.drain(..som_pos);
74 match ParsedPacket::parse(&self.rx_buf) {
75 Ok((parsed, used)) => {
76 let pd_addr = parsed.addr.pd_addr();
77 if pd_addr != self.address && !parsed.addr.is_broadcast() {
78 self.rx_buf.drain(..used);
80 continue;
81 }
82 let code = CommandCode::from_byte(parsed.code)?;
83 let sqn = parsed.ctrl.sqn.value();
84 let cmd_data = parsed.data.to_vec();
85 let used_len = used;
86 self.rx_buf.drain(..used_len);
87
88 if Some(sqn) == self.last_sqn {
89 if let Some(reply) = &self.last_reply {
91 let r = reply.clone();
92 self.transport.write_all(&r)?;
93 }
94 return Ok(true);
95 }
96
97 let command = Command::decode(code, &cmd_data)?;
98 let reply = self.handler.on_command(&command);
99 let bytes = self.encode_reply(sqn, &reply)?;
100 self.transport.write_all(&bytes)?;
101 self.last_sqn = Some(sqn);
102 self.last_reply = Some(bytes);
103 let _ = self.clock.now_ms();
104 return Ok(true);
105 }
106 Err(Error::Truncated { .. }) => return Ok(false),
107 Err(Error::BadSom(_)) => {
108 self.rx_buf.remove(0);
109 continue;
110 }
111 Err(other) => return Err(other),
112 }
113 }
114
115 Ok(false)
116 }
117
118 fn encode_reply(&self, sqn: u8, reply: &Reply) -> Result<Vec<u8>, Error> {
119 let addr = Address::reply(self.address)?;
120 let ctrl = ControlByte::new(
121 Sqn::new(sqn)?,
122 if self.use_crc {
123 CtrlFlags::USE_CRC
124 } else {
125 CtrlFlags::empty()
126 },
127 );
128 let data = reply.encode_data()?;
129 PacketBuilder::plain(addr, ctrl, reply.code().as_byte(), data).encode()
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::clock::MockClock;
137 use crate::command::Command;
138 use crate::reply::{Ack, Reply};
139 use crate::transport::VecTransport;
140
141 struct AlwaysAck;
142 impl PdHandler for AlwaysAck {
143 fn on_command(&mut self, _command: &Command) -> Reply {
144 Reply::Ack(Ack)
145 }
146 }
147
148 #[test]
149 fn dispatches_poll_to_ack() {
150 let clock = MockClock::new();
151 let mut transport = VecTransport::new();
152 let bytes = PacketBuilder::plain(
154 Address::pd(0x05).unwrap(),
155 ControlByte::new(Sqn::new(1).unwrap(), CtrlFlags::USE_CRC),
156 CommandCode::Poll.as_byte(),
157 Vec::new(),
158 )
159 .encode()
160 .unwrap();
161 transport.feed(&bytes);
162 let mut pd = Pd::new(transport, clock, 0x05, AlwaysAck);
163 assert!(pd.poll_once().unwrap());
164 let reply_bytes: Vec<u8> = pd.transport().outgoing.drain(..).collect();
165 let (parsed, _) = ParsedPacket::parse(&reply_bytes).unwrap();
166 assert_eq!(parsed.code, 0x40);
167 assert!(parsed.addr.is_reply());
168 }
169}