Skip to main content

rs_matter/dm/networks/
eth.rs

1/*
2 *
3 *    Copyright (c) 2025-2026 Project CHIP Authors
4 *
5 *    Licensed under the Apache License, Version 2.0 (the "License");
6 *    you may not use this file except in compliance with the License.
7 *    You may obtain a copy of the License at
8 *
9 *        http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS,
13 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *    See the License for the specific language governing permissions and
15 *    limitations under the License.
16 */
17
18//! This module contains the `Networks` trait implementation and the `NetCtl` trait implementation for Ethernet.
19
20use crate::dm::clusters::net_comm::{
21    self, NetCtl, NetCtlError, NetCtlStatus, NetworkCommissioningStatusEnum, NetworkScanInfo,
22    NetworkType, NetworksError, WirelessCreds,
23};
24use crate::error::{Error, ErrorCode};
25
26/// A fixed `Networks` trait implementation for Ethernet.
27///
28/// Ethernet does not need to manage networks, so it always reports 1 network
29/// and returns an error when trying to add or update networks.
30pub struct EthNetwork<'a> {
31    network_id: &'a str,
32}
33
34impl<'a> EthNetwork<'a> {
35    /// The network ID used by [`Self::new_default`] and [`EthNetCtl::new_default`].
36    pub const DEFAULT_ID: &'static str = "eth";
37
38    /// Create a new `EthNetwork` instance with a default network ID.
39    pub const fn new_default() -> Self {
40        Self::new(Self::DEFAULT_ID)
41    }
42
43    /// Create a new `EthNetwork` instance.
44    pub const fn new(network_id: &'a str) -> Self {
45        Self { network_id }
46    }
47}
48
49impl net_comm::Networks for EthNetwork<'_> {
50    fn max_networks(&self) -> Result<u8, Error> {
51        Ok(1)
52    }
53
54    fn networks(&self, f: &mut dyn FnMut(&[u8]) -> Result<(), Error>) -> Result<(), Error> {
55        f(self.network_id.as_bytes())
56    }
57
58    fn creds(
59        &self,
60        _network_id: &[u8],
61        _f: &mut dyn FnMut(&WirelessCreds) -> Result<(), Error>,
62    ) -> Result<u8, NetworksError> {
63        Err(NetworksError::Other(ErrorCode::InvalidAction.into()))
64    }
65
66    fn next_creds(
67        &self,
68        _last_network_id: Option<&[u8]>,
69        _f: &mut dyn FnMut(&WirelessCreds) -> Result<(), Error>,
70    ) -> Result<bool, Error> {
71        Err(ErrorCode::InvalidAction.into())
72    }
73
74    fn enabled(&self) -> Result<bool, Error> {
75        Ok(true)
76    }
77
78    fn set_enabled(&mut self, _enabled: bool) -> Result<(), Error> {
79        Ok(())
80    }
81
82    fn add_or_update(&mut self, _creds: &WirelessCreds<'_>) -> Result<u8, NetworksError> {
83        Err(NetworksError::Other(ErrorCode::InvalidAction.into()))
84    }
85
86    fn reorder(&mut self, _index: u8, _network_id: &[u8]) -> Result<u8, NetworksError> {
87        Err(NetworksError::Other(ErrorCode::InvalidAction.into()))
88    }
89
90    fn remove(&mut self, _network_id: &[u8]) -> Result<u8, NetworksError> {
91        Err(NetworksError::Other(ErrorCode::InvalidAction.into()))
92    }
93
94    fn managed(&self) -> Result<bool, Error> {
95        Ok(true)
96    }
97
98    fn set_managed(&mut self, _managed: bool) -> Result<(), Error> {
99        Ok(())
100    }
101
102    fn reset(&mut self) -> Result<(), Error> {
103        Ok(())
104    }
105
106    fn load(&mut self, _data: &[u8]) -> Result<(), Error> {
107        Ok(())
108    }
109
110    fn save(&self, _buf: &mut [u8]) -> Result<Option<usize>, Error> {
111        Ok(None)
112    }
113}
114
115/// A `net_comm::NetCtl` implementation for Ethernet that errors out on all methods.
116///
117/// The network ID it reports as `LastNetworkID` must match the one served by the
118/// [`EthNetwork`] paired with it, as the two together describe a single wired
119/// interface. Both default to [`EthNetwork::DEFAULT_ID`], so a custom ID has to
120/// be given to both.
121pub struct EthNetCtl<'a> {
122    network_id: &'a str,
123}
124
125impl<'a> EthNetCtl<'a> {
126    /// Create a new `EthNetCtl` instance with a default network ID.
127    pub const fn new_default() -> Self {
128        Self::new(EthNetwork::DEFAULT_ID)
129    }
130
131    /// Create a new `EthNetCtl` instance.
132    pub const fn new(network_id: &'a str) -> Self {
133        Self { network_id }
134    }
135}
136
137impl NetCtl for EthNetCtl<'_> {
138    fn net_type(&self) -> NetworkType {
139        NetworkType::Ethernet
140    }
141
142    async fn scan<F>(&self, _network: Option<&[u8]>, _f: F) -> Result<(), NetCtlError>
143    where
144        F: FnMut(&NetworkScanInfo) -> Result<(), Error>,
145    {
146        Err(NetCtlError::Other(ErrorCode::InvalidAction.into()))
147    }
148
149    async fn connect(&self, _creds: &WirelessCreds<'_>) -> Result<(), NetCtlError> {
150        Err(NetCtlError::Other(ErrorCode::InvalidAction.into()))
151    }
152}
153
154impl NetCtlStatus for EthNetCtl<'_> {
155    fn last_networking_status(&self) -> Result<Option<NetworkCommissioningStatusEnum>, Error> {
156        // The wired interface is up whenever this can be read at all, so the
157        // last (implicit) network operation is always a successful one.
158        Ok(Some(NetworkCommissioningStatusEnum::Success))
159    }
160
161    fn last_network_id<F, R>(&self, f: F) -> Result<R, Error>
162    where
163        F: FnOnce(Option<&[u8]>) -> Result<R, Error>,
164    {
165        f(Some(self.network_id.as_bytes()))
166    }
167
168    fn last_connect_error_value(&self) -> Result<Option<i32>, Error> {
169        Ok(None)
170    }
171}