1#![allow(unused)]
13
14use crate::{
15 AppCookie, MctpMessage, ReceiveHandle, SendOutput, Stack, MAX_PAYLOAD,
16};
17use heapless::Vec;
18use mctp::{Eid, Error, MsgIC, MsgType, Result, Tag};
19
20#[cfg(feature = "defmt")]
21#[allow(unused)]
22use defmt::{debug, error, info, trace, warn};
23
24#[cfg(feature = "log")]
25#[allow(unused)]
26use log::{debug, error, info, trace, warn};
27
28const HDR_LEN: usize = 4;
29const MCTP_USB_MTU_MAX: usize = u8::MAX as usize - HDR_LEN;
30const TX_XFER_SIZE: usize = 512;
31
32pub struct MctpUsbHandler {
33 tx_msg: Vec<u8, MAX_PAYLOAD>,
34 tx_xfer: [u8; TX_XFER_SIZE],
35}
36
37pub trait MctpUsbXfer {
38 fn send_xfer(&mut self, buf: &[u8]) -> Result<()>;
39}
40
41impl MctpUsbHandler {
42 pub fn new() -> Self {
43 Self {
44 tx_msg: Vec::new(),
45 tx_xfer: [0u8; TX_XFER_SIZE],
46 }
47 }
48
49 pub fn decode(xfer: &[u8]) -> Result<(&[u8], &[u8])> {
57 let (hdr, data) =
58 xfer.split_at_checked(HDR_LEN).ok_or(Error::RxFailure)?;
59
60 if hdr[0..2] != [0x1a, 0xb4] {
61 debug!("mismatch: {:x} {:x}", hdr[0], hdr[1]);
62 return Err(Error::RxFailure);
63 }
64
65 let Some(len) = (hdr[3] as usize).checked_sub(HDR_LEN) else {
66 trace!("Mismatch mctp usb len");
67 return Err(Error::RxFailure);
68 };
69
70 let Some(data) = data.split_at_checked(len) else {
71 trace!("Short mctp usb packet");
72 return Err(Error::RxFailure);
73 };
74 Ok(data)
75 }
76
77 pub fn receive<'f>(
78 xfer: &[u8],
79 mctp: &'f mut Stack,
80 ) -> Result<Option<(MctpMessage<'f>, ReceiveHandle)>> {
81 let (data, _rem) = Self::decode(xfer)?;
84 mctp.receive(data)
85 }
86
87 pub fn send_fill<F>(
88 &mut self,
89 eid: Eid,
90 typ: MsgType,
91 tag: Option<Tag>,
92 ic: MsgIC,
93 cookie: Option<AppCookie>,
94 xfer: &mut impl MctpUsbXfer,
95 mctp: &mut Stack,
96 fill_msg: F,
97 ) -> SendOutput<'_>
98 where
99 F: FnOnce(&mut Vec<u8, MAX_PAYLOAD>) -> Option<()>,
100 {
101 self.tx_msg.clear();
102 if fill_msg(&mut self.tx_msg).is_none() {
103 return SendOutput::Error {
104 err: Error::Other,
105 cookie: None,
106 };
107 }
108
109 let res = mctp.start_send(
110 eid,
111 typ,
112 tag,
113 true,
114 ic,
115 Some(MCTP_USB_MTU_MAX),
116 cookie,
117 );
118 let mut fragmenter = match res {
119 Ok(f) => f,
120 Err(err) => return SendOutput::Error { err, cookie: None },
121 };
122
123 loop {
124 let (mut hdr, mut data) = self.tx_xfer.split_at_mut(HDR_LEN);
125 let r = fragmenter.fragment(&self.tx_msg, data);
126 let len = match r {
127 SendOutput::Packet(p) => p.len(),
128 SendOutput::Complete { .. } | SendOutput::Error { .. } => {
129 return r.unborrowed().unwrap()
130 }
131 };
132 if Self::header(len, hdr).is_err() {
133 return SendOutput::Error {
134 err: Error::InternalError,
135 cookie: None,
136 };
137 }
138 let slice = &self.tx_xfer[0..len + 4];
139 let res = xfer.send_xfer(slice);
140 if let Err(_e) = res {
141 trace!("USB transfer error");
142 return SendOutput::Error {
143 err: Error::TxFailure,
144 cookie: None,
145 };
146 }
147 }
148 }
149
150 pub fn header(mctp_len: usize, hdr: &mut [u8]) -> Result<()> {
156 if hdr.len() != 4 {
157 return Err(Error::BadArgument);
158 }
159
160 let usb_len: u8 = mctp_len
161 .checked_add(4)
162 .ok_or(Error::BadArgument)?
163 .try_into()
164 .map_err(|_| Error::BadArgument)?;
165
166 hdr[0] = 0x1a;
167 hdr[1] = 0xb4;
168 hdr[2] = 0;
169 hdr[3] = usb_len;
170 Ok(())
171 }
172}
173
174impl Default for MctpUsbHandler {
175 fn default() -> Self {
176 Self::new()
177 }
178}