1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20#[non_exhaustive]
21pub enum Speed {
22 _10M,
24 _100M,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35#[non_exhaustive]
36pub enum Duplex {
37 Half,
39 Full,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub struct LinkState {
53 pub up: bool,
55 pub speed: Speed,
57 pub duplex: Duplex,
59}
60
61impl LinkState {
62 pub const fn down() -> Self {
68 Self {
69 up: false,
70 speed: Speed::_100M,
71 duplex: Duplex::Full,
72 }
73 }
74
75 pub const fn up(speed: Speed, duplex: Duplex) -> Self {
77 Self {
78 up: true,
79 speed,
80 duplex,
81 }
82 }
83}
84
85#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub struct PhyCapabilities {
89 pub speed_100_fd: bool,
91 pub speed_100_hd: bool,
93 pub speed_10_fd: bool,
95 pub speed_10_hd: bool,
97 pub auto_negotiation: bool,
99 pub pause: bool,
101}
102
103#[cfg(test)]
104mod tests {
105 extern crate alloc;
106
107 use super::*;
108 use alloc::format;
109
110 #[test]
111 fn link_state_up_constructor() {
112 let ls = LinkState::up(Speed::_100M, Duplex::Full);
113 assert!(ls.up);
114 assert_eq!(ls.speed, Speed::_100M);
115 assert_eq!(ls.duplex, Duplex::Full);
116 }
117
118 #[test]
119 fn link_state_down_constructor() {
120 let ls = LinkState::down();
121 assert!(!ls.up);
122 }
123
124 #[test]
125 fn link_state_equality() {
126 let a = LinkState::up(Speed::_10M, Duplex::Half);
127 let b = LinkState::up(Speed::_10M, Duplex::Half);
128 let c = LinkState::up(Speed::_100M, Duplex::Full);
129 assert_eq!(a, b);
130 assert_ne!(a, c);
131 assert_eq!(LinkState::down(), LinkState::down());
133 }
134
135 #[test]
136 fn link_state_all_up_combinations() {
137 let combos = [
138 LinkState::up(Speed::_10M, Duplex::Half),
139 LinkState::up(Speed::_10M, Duplex::Full),
140 LinkState::up(Speed::_100M, Duplex::Half),
141 LinkState::up(Speed::_100M, Duplex::Full),
142 ];
143 for i in 0..combos.len() {
144 for j in (i + 1)..combos.len() {
145 assert_ne!(combos[i], combos[j], "combo {i} == combo {j}");
146 }
147 }
148 }
149
150 #[test]
151 fn phy_capabilities_default_all_false() {
152 let caps = PhyCapabilities::default();
153 assert!(!caps.speed_100_fd);
154 assert!(!caps.speed_100_hd);
155 assert!(!caps.speed_10_fd);
156 assert!(!caps.speed_10_hd);
157 assert!(!caps.auto_negotiation);
158 assert!(!caps.pause);
159 }
160
161 #[test]
162 fn phy_capabilities_equality() {
163 let a = PhyCapabilities {
164 speed_100_fd: true,
165 auto_negotiation: true,
166 ..Default::default()
167 };
168 let b = PhyCapabilities {
169 speed_100_fd: true,
170 auto_negotiation: true,
171 ..Default::default()
172 };
173 let c = PhyCapabilities::default();
174 assert_eq!(a, b);
175 assert_ne!(a, c);
176 }
177
178 #[test]
179 fn speed_clone_copy() {
180 let s = Speed::_100M;
181 let s2 = s;
182 let s3 = Clone::clone(&s);
183 assert_eq!(s, s2);
184 assert_eq!(s, s3);
185 }
186
187 #[test]
188 fn duplex_clone_copy() {
189 let d = Duplex::Full;
190 let d2 = d;
191 let d3 = Clone::clone(&d);
192 assert_eq!(d, d2);
193 assert_eq!(d, d3);
194 }
195
196 #[test]
197 fn link_state_debug() {
198 let ls = LinkState::up(Speed::_100M, Duplex::Full);
199 let dbg = format!("{:?}", ls);
200 assert!(dbg.contains("_100M"), "debug missing Speed: {dbg}");
201 assert!(dbg.contains("Full"), "debug missing Duplex: {dbg}");
202 assert!(dbg.contains("up: true"), "debug missing up flag: {dbg}");
203 }
204}