Skip to main content

eth_mdio_phy/
types.rs

1// SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
2// Copyright (c) Viacheslav Bocharov <v@baodeep.com> and JetHome (r)
3
4//! Shared types for Ethernet PHY drivers.
5
6/// Ethernet link speed.
7///
8/// Marked `#[non_exhaustive]` so future variants (e.g. `Mbps1000` for
9/// gigabit-capable PHYs) can land as a non-breaking minor release —
10/// downstream `match` expressions are required to keep a wildcard arm.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13#[non_exhaustive]
14pub enum Speed {
15    /// 10 Mbps
16    Mbps10,
17    /// 100 Mbps
18    Mbps100,
19}
20
21/// Ethernet duplex mode.
22///
23/// Marked `#[non_exhaustive]` for symmetry with [`Speed`] — downstream
24/// `match` arms must include a wildcard so a future variant can land
25/// in a minor release.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28#[non_exhaustive]
29pub enum Duplex {
30    /// Half duplex
31    Half,
32    /// Full duplex
33    Full,
34}
35
36/// Negotiated or configured link parameters.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39pub struct LinkStatus {
40    /// Link speed
41    pub speed: Speed,
42    /// Duplex mode
43    pub duplex: Duplex,
44}
45
46impl LinkStatus {
47    /// Create a new link status.
48    pub const fn new(speed: Speed, duplex: Duplex) -> Self {
49        Self { speed, duplex }
50    }
51}
52
53/// PHY hardware capabilities.
54#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56pub struct PhyCapabilities {
57    /// 100BASE-TX full duplex
58    pub speed_100_fd: bool,
59    /// 100BASE-TX half duplex
60    pub speed_100_hd: bool,
61    /// 10BASE-T full duplex
62    pub speed_10_fd: bool,
63    /// 10BASE-T half duplex
64    pub speed_10_hd: bool,
65    /// Auto-negotiation supported
66    pub auto_negotiation: bool,
67    /// PAUSE flow control supported
68    pub pause: bool,
69}
70
71#[cfg(test)]
72mod tests {
73    extern crate alloc;
74
75    use super::*;
76    use alloc::format;
77
78    #[test]
79    fn link_status_new() {
80        let ls = LinkStatus::new(Speed::Mbps100, Duplex::Full);
81        assert_eq!(ls.speed, Speed::Mbps100);
82        assert_eq!(ls.duplex, Duplex::Full);
83    }
84
85    #[test]
86    fn link_status_equality() {
87        let a = LinkStatus::new(Speed::Mbps10, Duplex::Half);
88        let b = LinkStatus::new(Speed::Mbps10, Duplex::Half);
89        let c = LinkStatus::new(Speed::Mbps100, Duplex::Full);
90        assert_eq!(a, b);
91        assert_ne!(a, c);
92    }
93
94    #[test]
95    fn link_status_all_combinations() {
96        let combos = [
97            LinkStatus::new(Speed::Mbps10, Duplex::Half),
98            LinkStatus::new(Speed::Mbps10, Duplex::Full),
99            LinkStatus::new(Speed::Mbps100, Duplex::Half),
100            LinkStatus::new(Speed::Mbps100, Duplex::Full),
101        ];
102        for i in 0..combos.len() {
103            for j in (i + 1)..combos.len() {
104                assert_ne!(combos[i], combos[j], "combo {i} == combo {j}");
105            }
106        }
107    }
108
109    #[test]
110    fn phy_capabilities_default_all_false() {
111        let caps = PhyCapabilities::default();
112        assert!(!caps.speed_100_fd);
113        assert!(!caps.speed_100_hd);
114        assert!(!caps.speed_10_fd);
115        assert!(!caps.speed_10_hd);
116        assert!(!caps.auto_negotiation);
117        assert!(!caps.pause);
118    }
119
120    #[test]
121    fn phy_capabilities_equality() {
122        let a = PhyCapabilities {
123            speed_100_fd: true,
124            auto_negotiation: true,
125            ..Default::default()
126        };
127        let b = PhyCapabilities {
128            speed_100_fd: true,
129            auto_negotiation: true,
130            ..Default::default()
131        };
132        let c = PhyCapabilities::default();
133        assert_eq!(a, b);
134        assert_ne!(a, c);
135    }
136
137    #[test]
138    fn speed_clone_copy() {
139        let s = Speed::Mbps100;
140        let s2 = s;
141        let s3 = Clone::clone(&s);
142        assert_eq!(s, s2);
143        assert_eq!(s, s3);
144    }
145
146    #[test]
147    fn duplex_clone_copy() {
148        let d = Duplex::Full;
149        let d2 = d;
150        let d3 = Clone::clone(&d);
151        assert_eq!(d, d2);
152        assert_eq!(d, d3);
153    }
154
155    #[test]
156    fn link_status_debug() {
157        let ls = LinkStatus::new(Speed::Mbps100, Duplex::Full);
158        let dbg = format!("{:?}", ls);
159        assert!(dbg.contains("Mbps100"), "debug missing Speed: {dbg}");
160        assert!(dbg.contains("Full"), "debug missing Duplex: {dbg}");
161    }
162}