1#[allow(unused)]
9use crate::fmt::{debug, error, info, trace, warn};
10
11use crate::{
12 AppCookie, Fragmenter, MctpMessage, MsgIC, ReceiveHandle, SendOutput,
13 Stack, MAX_PAYLOAD,
14};
15use mctp::{Eid, Error, MsgType, Result, Tag};
16
17use heapless::Vec;
18
19pub const MCTP_I2C_COMMAND_CODE: u8 = 0x0f;
20
21const MCTP_I2C_HEADER: usize = 4;
22pub const MCTP_I2C_MAXMTU: usize = u8::MAX as usize - 1;
24
25type MctpI2cHeader =
26 libmctp::smbus_proto::MCTPSMBusHeader<[u8; MCTP_I2C_HEADER]>;
27
28#[derive(Debug, Clone)]
30pub struct MctpI2cEncap {
31 own_addr: u8,
32}
33
34impl MctpI2cEncap {
35 pub fn new(own_addr: u8) -> Self {
36 Self { own_addr }
37 }
38
39 pub fn own_addr(&self) -> u8 {
40 self.own_addr
41 }
42
43 pub fn decode<'f>(
44 &self,
45 mut packet: &'f [u8],
46 pec: bool,
47 ) -> Result<(&'f [u8], u8)> {
48 if pec {
49 if packet.is_empty() {
51 return Err(Error::InvalidInput);
52 }
53 let packet_pec;
54 (packet_pec, packet) = packet.split_last().unwrap();
55 let calc_pec = smbus_pec::pec(packet);
56 if calc_pec != *packet_pec {
57 trace!("Incorrect PEC");
58 return Err(Error::InvalidInput);
59 }
60 }
61
62 if packet.len() < MCTP_I2C_HEADER {
63 return Err(Error::InvalidInput);
64 }
65
66 let (i2c, packet) = packet.split_at(MCTP_I2C_HEADER);
67 let header = MctpI2cHeader::new_from_buf(i2c.try_into().unwrap());
69 if header.byte_count() as usize != packet.len() + 1 {
71 return Err(Error::InvalidInput);
72 }
73
74 if header.command_code() != MCTP_I2C_COMMAND_CODE {
75 return Err(Error::InvalidInput);
76 }
77 Ok((packet, header.source_slave_addr()))
78 }
79
80 pub fn receive_done_pec<'f>(
85 &self,
86 packet: &[u8],
87 mctp: &'f mut Stack,
88 ) -> Result<Option<(MctpMessage<'f>, u8, ReceiveHandle)>> {
89 let (mctp_packet, i2c_src) = self.decode(packet, false)?;
90
91 let m = mctp.receive(mctp_packet)?;
93
94 Ok(m.map(|(msg, handle)| (msg, i2c_src, handle)))
96 }
97
98 pub fn send<'f>(
102 &self,
103 i2c_dest: u8,
104 payload: &[u8],
105 out: &'f mut [u8],
106 fragmenter: &mut Fragmenter,
107 ) -> SendOutput<'f> {
108 if out.len() < MCTP_I2C_HEADER {
109 return SendOutput::failure(Error::InvalidInput, fragmenter);
110 }
111
112 let (i2chead, packet) = out.split_at_mut(MCTP_I2C_HEADER);
113
114 let r = fragmenter.fragment(payload, packet);
116 let packet = match r {
117 SendOutput::Packet(packet) => packet,
118 SendOutput::Complete { .. } | SendOutput::Error { .. } => {
120 return r.unborrowed().unwrap()
121 }
122 };
123
124 let mut header = MctpI2cHeader::new();
126 header.set_dest_slave_addr(i2c_dest);
127 header.set_source_slave_addr(self.own_addr);
128 header.set_source_read_write(1);
129 header.set_command_code(MCTP_I2C_COMMAND_CODE);
130 debug_assert!(packet.len() <= MCTP_I2C_MAXMTU);
131 header.set_byte_count((packet.len() + 1) as u8);
132
133 i2chead.copy_from_slice(&header.0);
134
135 let out_len = MCTP_I2C_HEADER + packet.len();
136 let out = &mut out[..out_len];
137 SendOutput::Packet(out)
138 }
139
140 pub fn encode<'f>(
141 &self,
142 i2c_dest: u8,
143 inp: &[u8],
144 out: &'f mut [u8],
145 pec: bool,
146 ) -> Result<&'f mut [u8]> {
147 let pec_extra = pec as usize;
148 let out_len = MCTP_I2C_HEADER + inp.len() + pec_extra;
149 if out.len() < out_len {
150 return Err(Error::BadArgument);
151 }
152 if inp.len() > MCTP_I2C_MAXMTU {
153 return Err(Error::BadArgument);
154 }
155
156 let (i2chead, packet) = out.split_at_mut(MCTP_I2C_HEADER);
157 let mut header = MctpI2cHeader::new();
158 header.set_dest_slave_addr(i2c_dest);
159 header.set_source_slave_addr(self.own_addr);
160 header.set_source_read_write(1);
161 header.set_command_code(MCTP_I2C_COMMAND_CODE);
162 header.set_byte_count((1 + inp.len()) as u8);
164 i2chead.copy_from_slice(&header.0);
165 packet[..inp.len()].copy_from_slice(inp);
166
167 if pec {
168 let pec_content = &out[..MCTP_I2C_HEADER + inp.len()];
169 out[MCTP_I2C_HEADER + inp.len()] = smbus_pec::pec(pec_content);
170 }
171 Ok(&mut out[..out_len])
172 }
173}
174
175pub struct MctpI2cHandler {
179 encap: MctpI2cEncap,
180
181 send_message: &'static mut Vec<u8, MAX_PAYLOAD>,
182 send_state: HandlerSendState,
183}
184
185impl core::fmt::Debug for MctpI2cHandler {
186 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 f.debug_struct("MctpI2cHandler")
188 .field("send_state", &self.send_state)
189 .finish_non_exhaustive()
190 }
191}
192
193impl MctpI2cHandler {
194 pub fn new(
200 own_addr: u8,
201 send_message: &'static mut Vec<u8, MAX_PAYLOAD>,
202 ) -> Self {
203 Self {
204 encap: MctpI2cEncap::new(own_addr),
205 send_message,
206 send_state: HandlerSendState::Idle,
207 }
208 }
209
210 pub fn receive<'f>(
218 &mut self,
219 packet: &[u8],
220 mctp: &'f mut Stack,
221 ) -> Result<Option<(MctpMessage<'f>, u8, ReceiveHandle)>> {
222 self.encap.receive_done_pec(packet, mctp)
223 }
224
225 pub fn is_send_ready(&self) -> bool {
227 matches!(self.send_state, HandlerSendState::Sending { .. })
228 }
229
230 pub fn is_send_idle(&self) -> bool {
232 matches!(self.send_state, HandlerSendState::Idle)
233 }
234
235 pub fn send_fill<'f>(&mut self, buf: &'f mut [u8]) -> SendOutput<'f> {
241 let HandlerSendState::Sending {
242 fragmenter,
243 i2c_dest,
244 } = &mut self.send_state
245 else {
246 debug_assert!(false, "called when not !is_send_ready()");
247 return SendOutput::bare_failure(Error::Other);
248 };
249
250 let r = self
251 .encap
252 .send(*i2c_dest, self.send_message, buf, fragmenter);
253 match r {
254 SendOutput::Complete { .. } | SendOutput::Error { .. } => {
255 self.send_message.clear();
256 self.send_state = HandlerSendState::Idle;
257 }
258 SendOutput::Packet(_) => (),
259 };
260 r
261 }
262
263 pub fn cancel_send(&mut self) -> Option<AppCookie> {
264 let mut cookie = None;
265 if let HandlerSendState::Sending { fragmenter, .. } =
266 &mut self.send_state
267 {
268 cookie = fragmenter.cookie();
269 }
270 self.send_message.clear();
271 self.send_state = HandlerSendState::Idle;
272 cookie
273 }
274
275 pub fn send_enqueue<F>(
288 &mut self,
289 eid: Eid,
290 typ: MsgType,
291 tag: Option<Tag>,
292 ic: MsgIC,
293 i2c_dest: u8,
294 cookie: Option<AppCookie>,
295 mctp: &mut Stack,
296 fill_msg: F,
297 ) -> Result<()>
298 where
299 F: FnOnce(&mut Vec<u8, MAX_PAYLOAD>) -> Option<()>,
300 {
301 if !self.is_send_idle() {
302 return Err(Error::Other);
303 }
304 if !self.send_message.is_empty() {
306 trace!("sendmsg not empty");
307 }
308
309 fill_msg(self.send_message).ok_or(Error::InvalidInput)?;
312
313 let fragmenter = mctp.start_send(
314 eid,
315 typ,
316 tag,
317 true,
318 ic,
319 Some(MCTP_I2C_MAXMTU),
320 cookie,
321 )?;
322 self.send_state = HandlerSendState::Sending {
323 fragmenter,
324 i2c_dest,
325 };
326 Ok(())
327 }
328}
329
330#[derive(Debug)]
331enum HandlerSendState {
332 Idle,
333 Sending {
334 fragmenter: Fragmenter,
335 i2c_dest: u8,
336 },
337}