ergot_base/interface_manager/profiles/direct_edge/
mod.rs1use log::{debug, trace};
14use serde::Serialize;
15
16#[cfg(feature = "embassy-usb-v0_4")]
17pub mod eusb_0_4;
18
19#[cfg(feature = "embassy-usb-v0_5")]
20pub mod eusb_0_5;
21
22#[cfg(feature = "std")]
23pub mod std_tcp;
24
25use crate::{
26 Header, ProtocolError,
27 interface_manager::{
28 Interface, InterfaceSendError, InterfaceSink, InterfaceState, Profile, SetStateError,
29 },
30 wire_frames::CommonHeader,
31};
32
33pub const CENTRAL_NODE_ID: u8 = 1;
34pub const EDGE_NODE_ID: u8 = 2;
35
36pub enum SetNetIdError {
37 CantSetZero,
38 NoActiveSink,
39}
40
41pub struct DirectEdge<I: Interface> {
43 sink: I::Sink,
44 seq_no: u16,
45 state: InterfaceState,
46 own_node_id: u8,
47 other_node_id: u8,
48}
49
50impl<I: Interface> DirectEdge<I> {
51 pub const fn new_target(sink: I::Sink) -> Self {
52 Self {
53 sink,
54 seq_no: 0,
55 state: InterfaceState::Down,
56 own_node_id: EDGE_NODE_ID,
57 other_node_id: CENTRAL_NODE_ID,
58 }
59 }
60
61 pub const fn new_controller(sink: I::Sink, state: InterfaceState) -> Self {
62 Self {
63 sink,
64 seq_no: 0,
65 state,
66 own_node_id: CENTRAL_NODE_ID,
67 other_node_id: EDGE_NODE_ID,
68 }
69 }
70}
71
72impl<I: Interface> DirectEdge<I> {
73 fn common_send<'b>(
74 &'b mut self,
75 ihdr: &Header,
76 ) -> Result<(&'b mut I::Sink, CommonHeader), InterfaceSendError> {
77 let net_id = match &self.state {
78 InterfaceState::Down | InterfaceState::Inactive => {
79 return Err(InterfaceSendError::NoRouteToDest);
80 }
81 InterfaceState::ActiveLocal { .. } => {
82 return Err(InterfaceSendError::NoRouteToDest);
84 }
85 InterfaceState::Active { net_id, node_id: _ } => *net_id,
86 };
87
88 trace!("common_send header: {:?}", ihdr);
89
90 if net_id == 0 {
91 debug!("Attempted to send via interface before we have been assigned a net ID");
92 return Err(InterfaceSendError::NoRouteToDest);
94 }
95 if ihdr.dst.network_id == net_id && ihdr.dst.node_id == self.own_node_id {
101 return Err(InterfaceSendError::DestinationLocal);
102 }
103
104 let mut hdr = ihdr.clone();
107 hdr.decrement_ttl()?;
108
109 if hdr.src.net_node_any() {
112 hdr.src.network_id = net_id;
116 hdr.src.node_id = self.own_node_id;
117 }
118
119 if hdr.dst.port_id == 255 {
122 hdr.dst.network_id = net_id;
123 hdr.dst.node_id = self.other_node_id;
124 }
125
126 let seq_no = self.seq_no;
127 self.seq_no = self.seq_no.wrapping_add(1);
128
129 let header = CommonHeader {
130 src: hdr.src,
131 dst: hdr.dst,
132 seq_no,
133 kind: hdr.kind,
134 ttl: hdr.ttl,
135 };
136 if [0, 255].contains(&hdr.dst.port_id) && ihdr.any_all.is_none() {
137 return Err(InterfaceSendError::AnyPortMissingKey);
138 }
139
140 Ok((&mut self.sink, header))
141 }
142}
143
144impl<I: Interface> Profile for DirectEdge<I> {
145 type InterfaceIdent = ();
146
147 fn send<T: Serialize>(&mut self, hdr: &Header, data: &T) -> Result<(), InterfaceSendError> {
148 let (intfc, header) = self.common_send(hdr)?;
149
150 let res = intfc.send_ty(&header, hdr.any_all.as_ref(), data);
151
152 match res {
153 Ok(()) => Ok(()),
154 Err(()) => Err(InterfaceSendError::InterfaceFull),
155 }
156 }
157
158 fn send_err(&mut self, hdr: &Header, err: ProtocolError) -> Result<(), InterfaceSendError> {
159 let (intfc, header) = self.common_send(hdr)?;
160
161 let res = intfc.send_err(&header, err);
162
163 match res {
164 Ok(()) => Ok(()),
165 Err(()) => Err(InterfaceSendError::InterfaceFull),
166 }
167 }
168
169 fn send_raw(
170 &mut self,
171 hdr: &Header,
172 hdr_raw: &[u8],
173 data: &[u8],
174 ) -> Result<(), InterfaceSendError> {
175 let (intfc, header) = self.common_send(hdr)?;
176
177 let res = intfc.send_raw(&header, hdr_raw, data);
178
179 match res {
180 Ok(()) => Ok(()),
181 Err(()) => Err(InterfaceSendError::InterfaceFull),
182 }
183 }
184
185 fn interface_state(&mut self, _ident: ()) -> Option<InterfaceState> {
186 Some(self.state)
187 }
188
189 fn set_interface_state(
190 &mut self,
191 _ident: (),
192 state: InterfaceState,
193 ) -> Result<(), SetStateError> {
194 match state {
195 InterfaceState::Down => {
196 self.state = InterfaceState::Down;
197 }
198 InterfaceState::Inactive => {
199 self.state = InterfaceState::Inactive;
200 }
201 InterfaceState::ActiveLocal { node_id } => {
202 if node_id != self.own_node_id {
203 return Err(SetStateError::InvalidNodeId);
204 }
205 self.state = InterfaceState::ActiveLocal { node_id };
206 }
207 InterfaceState::Active { net_id, node_id } => {
208 if node_id != self.own_node_id {
209 return Err(SetStateError::InvalidNodeId);
210 }
211 self.state = InterfaceState::Active { net_id, node_id };
212 }
213 }
214 Ok(())
215 }
216}