Skip to main content

rs_matter/dm/networks/wireless/
wifi.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 Wifi-specific types.
19
20use core::fmt::{Debug, Display};
21
22use crate::dm::clusters::net_comm::WirelessCreds;
23use crate::error::{Error, ErrorCode};
24use crate::tlv::{FromTLV, OctetsOwned, ToTLV};
25use crate::utils::init::{init, Init, IntoFallibleInit};
26use crate::utils::storage::Vec;
27
28use super::{WirelessNetwork, WirelessNetworks};
29
30pub type WifiNetworks<const N: usize> = WirelessNetworks<N, Wifi>;
31
32/// A struct implementing the `WirelessNetwork` trait for Wifi networks.
33#[derive(Debug, Clone, Eq, PartialEq, Hash, ToTLV, FromTLV)]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35pub struct Wifi {
36    /// Wifi SSID
37    pub ssid: OctetsOwned<32>,
38    /// Wifi password
39    pub password: OctetsOwned<64>,
40}
41
42impl Default for Wifi {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl Wifi {
49    /// Create a new, empty instance of `Wifi`.
50    pub const fn new() -> Self {
51        Self {
52            ssid: OctetsOwned { vec: Vec::new() },
53            password: OctetsOwned { vec: Vec::new() },
54        }
55    }
56
57    /// Return an in-place initializer for an empty `Wifi` instance.
58    pub fn init() -> impl Init<Self> {
59        init!(Self {
60            ssid <- OctetsOwned::init(),
61            password <- OctetsOwned::init(),
62        })
63    }
64}
65
66impl WirelessNetwork for Wifi {
67    fn id(&self) -> &[u8] {
68        &self.ssid
69    }
70
71    #[cfg(not(feature = "defmt"))]
72    fn display_id(id: &[u8]) -> impl Display {
73        use super::DisplayId;
74
75        DisplayId::Wifi(id)
76    }
77
78    #[cfg(feature = "defmt")]
79    fn display_id(id: &[u8]) -> impl Display + defmt::Format {
80        use super::DisplayId;
81
82        DisplayId::Wifi(id)
83    }
84
85    fn init_from<'a>(creds: &'a WirelessCreds<'a>) -> impl Init<Self, Error> + 'a {
86        Self::init().into_fallible().chain(move |network| {
87            let WirelessCreds::Wifi { ssid, pass } = creds else {
88                return Err(ErrorCode::InvalidData.into());
89            };
90
91            network
92                .ssid
93                .vec
94                .extend_from_slice(ssid)
95                .map_err(|_| ErrorCode::InvalidData)?;
96            network
97                .password
98                .vec
99                .extend_from_slice(pass)
100                .map_err(|_| ErrorCode::InvalidData)?;
101
102            Ok(())
103        })
104    }
105
106    fn update(&mut self, creds: &WirelessCreds<'_>) -> Result<(), Error> {
107        let WirelessCreds::Wifi { ssid, pass } = creds else {
108            return Err(ErrorCode::InvalidData.into());
109        };
110
111        if ssid.len() > self.ssid.vec.capacity() {
112            return Err(ErrorCode::InvalidData.into());
113        }
114
115        if pass.len() > self.password.vec.capacity() {
116            return Err(ErrorCode::InvalidData.into());
117        }
118
119        self.ssid.vec.clear();
120        self.password.vec.clear();
121
122        unwrap!(self.ssid.vec.extend_from_slice(ssid));
123        unwrap!(self.password.vec.extend_from_slice(pass));
124
125        Ok(())
126    }
127
128    fn creds(&self) -> WirelessCreds<'_> {
129        WirelessCreds::Wifi {
130            ssid: &self.ssid.vec,
131            pass: &self.password.vec,
132        }
133    }
134}