Matter SDK Coverage Report
Current view: top level - include/platform - NetworkCommissioning.h (source / functions) Coverage Total Hit
Test: SHA:4d2388ac7eed75b2fe5e05e20de377999c632502 Lines: 50.0 % 16 8
Test Date: 2025-07-27 07:17:09 Functions: 34.5 % 29 10

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 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              : /**
      19              :  *    @file
      20              :  *      This file defines the CHIP Device Network Provisioning object.
      21              :  *
      22              :  */
      23              : 
      24              : #pragma once
      25              : 
      26              : #include <credentials/CHIPCert.h>
      27              : #include <crypto/CHIPCryptoPAL.h>
      28              : #include <lib/core/CHIPCore.h>
      29              : #include <lib/core/CHIPSafeCasts.h>
      30              : #include <lib/core/Optional.h>
      31              : #include <lib/support/ThreadOperationalDataset.h>
      32              : #include <lib/support/TypeTraits.h>
      33              : #include <lib/support/Variant.h>
      34              : #include <platform/CHIPDeviceConfig.h>
      35              : #include <platform/internal/DeviceNetworkInfo.h>
      36              : 
      37              : #include <app-common/zap-generated/cluster-enums.h>
      38              : 
      39              : #include <limits>
      40              : 
      41              : namespace chip {
      42              : namespace DeviceLayer {
      43              : /**
      44              :  * We are using a namespace here, for most use cases, this namespace will be used by `using DeviceLayer::NetworkCommissioning`, but
      45              :  * this still worth a dedicated namespace since:
      46              :  *
      47              :  * - The BaseDriver / WirelessDriver is not expected to be implemented directly by users, the only occurrence is in the network
      48              :  *   commissioning cluster.
      49              :  * - We can safely name the drivers as WiFiDriver / ThreadDriver, it should not be ambiguous for most cases
      50              :  * - We can safely name the Status enum to Status, and some other structs -- if we are using using, then we should in the context of
      51              :  *   writing something dedicated to network commissioning, then a single word Status should be clear enough.
      52              :  */
      53              : namespace NetworkCommissioning {
      54              : 
      55              : inline constexpr size_t kMaxNetworkIDLen = 32;
      56              : 
      57              : // TODO: This is exactly the same as the one in GroupDataProvider, this could be moved to src/lib/support
      58              : template <typename T>
      59              : class Iterator
      60              : {
      61              : public:
      62            2 :     virtual ~Iterator() = default;
      63              :     /**
      64              :      *  @retval The number of entries in total that will be iterated.
      65              :      */
      66              :     virtual size_t Count() = 0;
      67              :     /**
      68              :      *   @param[out] item  Value associated with the next element in the iteration.
      69              :      *  @retval true if the next entry is successfully retrieved.
      70              :      *  @retval false if no more entries can be found.
      71              :      */
      72              :     virtual bool Next(T & item) = 0;
      73              :     /**
      74              :      * Release the memory allocated by this iterator.
      75              :      * Must be called before the pointer goes out of scope.
      76              :      */
      77              :     virtual void Release() = 0;
      78              : 
      79              : protected:
      80            2 :     Iterator() = default;
      81              : };
      82              : 
      83              : // The following structs follows the generated cluster object structs.
      84              : struct Network
      85              : {
      86              :     uint8_t networkID[kMaxNetworkIDLen];
      87              :     uint8_t networkIDLen = 0;
      88              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
      89              :     Optional<Credentials::CertificateKeyIdStorage> networkIdentifier;
      90              :     Optional<Credentials::CertificateKeyIdStorage> clientIdentifier;
      91              : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
      92              :     bool connected = false;
      93              : };
      94              : 
      95              : static_assert(sizeof(Network::networkID) <= std::numeric_limits<decltype(Network::networkIDLen)>::max(),
      96              :               "Max length of networkID ssid exceeds the limit of networkIDLen field");
      97              : 
      98              : struct WiFiScanResponse
      99              : {
     100              : public:
     101              :     chip::BitFlags<app::Clusters::NetworkCommissioning::WiFiSecurityBitmap> security;
     102              :     uint8_t ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength];
     103              :     uint8_t ssidLen;
     104              :     uint8_t bssid[6];
     105              :     uint16_t channel;
     106              :     app::Clusters::NetworkCommissioning::WiFiBandEnum wiFiBand;
     107              :     int8_t rssi;
     108              : };
     109              : 
     110              : static_assert(sizeof(WiFiScanResponse::ssid) <= std::numeric_limits<decltype(WiFiScanResponse::ssidLen)>::max(),
     111              :               "Max length of WiFi ssid exceeds the limit of ssidLen field");
     112              : 
     113              : struct ThreadScanResponse
     114              : {
     115              :     uint16_t panId;
     116              :     uint64_t extendedPanId;
     117              :     char networkName[16];
     118              :     uint8_t networkNameLen;
     119              :     uint16_t channel;
     120              :     uint8_t version;
     121              :     uint64_t extendedAddress;
     122              :     int8_t rssi;
     123              :     uint8_t lqi;
     124              : };
     125              : 
     126              : static_assert(sizeof(ThreadScanResponse::networkName) <= std::numeric_limits<decltype(ThreadScanResponse::networkNameLen)>::max(),
     127              :               "Max length of WiFi credentials exceeds the limit of credentialsLen field");
     128              : 
     129              : using NetworkIterator            = Iterator<Network>;
     130              : using WiFiScanResponseIterator   = Iterator<WiFiScanResponse>;
     131              : using ThreadScanResponseIterator = Iterator<ThreadScanResponse>;
     132              : using Status                     = app::Clusters::NetworkCommissioning::NetworkCommissioningStatusEnum;
     133              : using WiFiBandEnum               = app::Clusters::NetworkCommissioning::WiFiBandEnum;
     134              : // For backwards compatibility with pre-rename enum values.
     135              : using WiFiBand           = WiFiBandEnum;
     136              : using WiFiSecurityBitmap = app::Clusters::NetworkCommissioning::WiFiSecurityBitmap;
     137              : // For backwards compatibility with pre-rename bitmap values.
     138              : using WiFiSecurity       = WiFiSecurityBitmap;
     139              : using ThreadCapabilities = app::Clusters::NetworkCommissioning::ThreadCapabilitiesBitmap;
     140              : 
     141              : // BaseDriver and WirelessDriver are the common interfaces for a network driver, platform drivers should not implement this
     142              : // directly, instead, users are expected to implement WiFiDriver, ThreadDriver and EthernetDriver.
     143              : namespace Internal {
     144              : class BaseDriver
     145              : {
     146              : public:
     147              :     class NetworkStatusChangeCallback
     148              :     {
     149              :     public:
     150              :         /**
     151              :          * @brief Callback for the network driver pushing the event of network status change to the network commissioning cluster.
     152              :          * The platforms is expected to push the status from operations such as autonomous connection after loss of connectivity or
     153              :          * during initial establishment.
     154              :          *
     155              :          * This function must be called in a thread-safe manner with CHIP stack.
     156              :          */
     157              :         virtual void OnNetworkingStatusChange(Status commissioningError, Optional<ByteSpan> networkId,
     158              :                                               Optional<int32_t> connectStatus) = 0;
     159              : 
     160            2 :         virtual ~NetworkStatusChangeCallback() = default;
     161              :     };
     162              : 
     163              :     /**
     164              :      * @brief Initializes the driver, this function will be called when initializing the network commissioning cluster.
     165              :      */
     166            0 :     virtual CHIP_ERROR Init(NetworkStatusChangeCallback * networkStatusChangeCallback) { return CHIP_NO_ERROR; }
     167              : 
     168              :     /**
     169              :      * @brief Shuts down the driver, this function will be called when shutting down the network commissioning cluster.
     170              :      */
     171            0 :     virtual void Shutdown() {}
     172              : 
     173              :     /**
     174              :      * @brief Returns maximum number of network configs can be added to the driver.
     175              :      */
     176              :     virtual uint8_t GetMaxNetworks() = 0;
     177              : 
     178              :     /**
     179              :      * @brief Returns an iterator for reading the networks, the user will always call NetworkIterator::Release. The iterator should
     180              :      * be consumed in the same context as calling GetNetworks(). Users must call Release() when the iterator goes out of scope.
     181              :      */
     182              :     virtual NetworkIterator * GetNetworks() = 0;
     183              : 
     184              :     /**
     185              :      * @brief Sets the status of the interface, this is an optional feature of a network driver.
     186              :      */
     187            0 :     virtual CHIP_ERROR SetEnabled(bool enabled) { return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; }
     188              : 
     189              :     /**
     190              :      * @brief Returns the status of the interface, this is an optional feature of a network driver the driver will be enabled by
     191              :      * default.
     192              :      */
     193            0 :     virtual bool GetEnabled() { return true; };
     194              : 
     195            2 :     virtual ~BaseDriver() = default;
     196              : };
     197              : 
     198              : class WirelessDriver : public Internal::BaseDriver
     199              : {
     200              : public:
     201              :     class ConnectCallback
     202              :     {
     203              :     public:
     204              :         virtual void OnResult(Status commissioningError, CharSpan debugText, int32_t connectStatus) = 0;
     205              : 
     206            2 :         virtual ~ConnectCallback() = default;
     207              :     };
     208              : 
     209              :     /**
     210              :      * @brief Persists the network configurations. This function is expected to be called when CommissioningComplete event is fired.
     211              :      */
     212              :     virtual CHIP_ERROR CommitConfiguration() = 0;
     213              : 
     214              :     /**
     215              :      * @brief Reverts the network configurations to the last committed one. This function is expected to be called when failsafe
     216              :      * timeout reached.
     217              :      */
     218              :     virtual CHIP_ERROR RevertConfiguration() = 0;
     219              : 
     220              :     virtual uint8_t GetScanNetworkTimeoutSeconds()    = 0;
     221              :     virtual uint8_t GetConnectNetworkTimeoutSeconds() = 0;
     222              : 
     223              :     /**
     224              :      * @brief Remove a network from the device. The driver should fill the outDebugText field to pass any human-readable messages to
     225              :      * the client. The driver should reduce the size of outDebugText to 0 to omit it from the response when no debug text needs to
     226              :      * be delivered. On success, the driver should set outNetworkIndex to the index of the network just removed. The value of
     227              :      * network index is discarded on failure.
     228              :      *
     229              :      * Note: The capacity of outDebugText passed by network commissioning cluster can be configured via
     230              :      * CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE.
     231              :      */
     232              :     virtual Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) = 0;
     233              : 
     234              :     /**
     235              :      * @brief Reorder the networks on the device. The driver should fill the outDebugText field to pass any human-readable messages
     236              :      * to the client. The driver should reduce the size of outDebugText to 0 to omit it from the response when no debug text needs
     237              :      * to be delivered.
     238              :      *
     239              :      * Note: The capacity of outDebugText passed by network commissioning cluster can be configured via
     240              :      * CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE.
     241              :      */
     242              :     virtual Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) = 0;
     243              : 
     244              :     /**
     245              :      * @brief Initializes a network join. callback->OnResult must be called, on both success and error. Callback can be
     246              :      * called inside ConnectNetwork.
     247              :      */
     248              :     virtual void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) = 0;
     249              : 
     250              : #if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
     251              :     /**
     252              :      * @brief Disconnect from network, if currently connected.
     253              :      */
     254            0 :     virtual CHIP_ERROR DisconnectFromNetwork() { return CHIP_ERROR_NOT_IMPLEMENTED; }
     255              : #endif
     256              : };
     257              : } // namespace Internal
     258              : 
     259              : class WiFiDriver : public Internal::WirelessDriver
     260              : {
     261              : public:
     262              :     class ScanCallback
     263              :     {
     264              :     public:
     265              :         /**
     266              :          * Indicates the scan is finished, and accepts a iterator of networks discovered.
     267              :          * - networks can be nullptr when no networks discovered, or error occurred during scanning the networks.
     268              :          * OnFinished() must be called in a thread-safe manner with CHIP stack. (e.g. using ScheduleWork or ScheduleLambda)
     269              :          * - Users can assume the networks will always be used (and Release will be called) inside this function call. However, the
     270              :          * iterator might be not fully consumed (i.e. There are too many networks scanned to fit in the buffer for scan response
     271              :          * message.)
     272              :          */
     273              :         virtual void OnFinished(Status status, CharSpan debugText, WiFiScanResponseIterator * networks) = 0;
     274              : 
     275            2 :         virtual ~ScanCallback() = default;
     276              :     };
     277              : 
     278              :     /**
     279              :      * @brief Adds or updates a WiFi network on the device. The driver should fill the outDebugText field to pass any human-readable
     280              :      * messages to the client. The driver should reduce the size of outDebugText to 0 to omit it from the response when no debug
     281              :      * text needs to be delivered. On success, the driver should set outNetworkIndex to the index of the network just added or
     282              :      * updated. The value of network index is discarded on failure.
     283              :      *
     284              :      * Note: The capacity of outDebugText passed by network commissioning cluster can be configured via
     285              :      * CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE.
     286              :      */
     287              :     virtual Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,
     288              :                                       uint8_t & outNetworkIndex) = 0;
     289              : 
     290              :     /**
     291              :      * @brief Initializes a WiFi network scan. callback->OnFinished must be called, on both success and error. Callback can
     292              :      * be called inside ScanNetworks.
     293              :      *
     294              :      * @param ssid        The interested SSID, the scanning SHALL be restricted to the given SSID if the ssid is not empty (i.e.
     295              :      *                    ssid.empty() is false).
     296              :      * @param callback    Callback that will be invoked upon finishing the scan
     297              :      */
     298              :     virtual void ScanNetworks(ByteSpan ssid, ScanCallback * callback) = 0;
     299              : 
     300              : #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
     301              :     virtual bool SupportsPerDeviceCredentials() { return false; };
     302              : 
     303              :     /**
     304              :      * @brief Adds or updates a WiFi network with Per-Device Credentials on the device.
     305              :      *
     306              :      * @param ssid                          The SSID of the network to be added / updated.
     307              :      * @param networkIdentity               The Network Identity of the network, in compact-pdc-identity format.
     308              :      * @param clientIdentityNetworkIndex    If present, the index of the existing network configuration of which the Client
     309              :      *                                      Identity is to be re-used. Otherwise a new Client Identity shall be generated.
     310              :      * @param outStatus                     The application-level status code (Status::kSuccess on success).
     311              :      * @param outDebugText                  A debug text buffer that may be populated by the driver. The size of the span
     312              :      *                                      must be reduced to the length of text emitted (or 0, if none).
     313              :      * @param outClientIdentity             On success, the Client Identity that was generated or copied, depending on the
     314              :      *                                      presence of `clientIdentityNetworkIndex`.
     315              :      * @param outNextworkIndex              On success, the index of the network entry that was added or updated.
     316              :      *
     317              :      * @retval CHIP_NO_ERROR and outStatus == kSuccess on success.
     318              :      * @retval CHIP_NO_ERROR and outStatus != kSuccess for application-level errors. outDebugText should be populated.
     319              :      * @retval CHIP_ERROR_* on internal errors. None of the output parameters will be examined in this case.
     320              :      */
     321              :     virtual CHIP_ERROR AddOrUpdateNetworkWithPDC(ByteSpan ssid, ByteSpan networkIdentity,
     322              :                                                  Optional<uint8_t> clientIdentityNetworkIndex, Status & outStatus,
     323              :                                                  MutableCharSpan & outDebugText, MutableByteSpan & outClientIdentity,
     324              :                                                  uint8_t & outNetworkIndex)
     325              :     {
     326              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     327              :     }
     328              : 
     329              :     /**
     330              :      * @brief Retrieves the Network Identity associated with a network.
     331              :      *
     332              :      * @param networkIndex          The 0-based index of the network.
     333              :      * @param outNetworkIdentity    The output buffer to be populated with the Network
     334              :      *                              Identity in compact-pdc-identity TLV format.
     335              :      *
     336              :      * @return CHIP_NO_ERROR on success or a CHIP_ERROR on failure.
     337              :      */
     338              :     virtual CHIP_ERROR GetNetworkIdentity(uint8_t networkIndex, MutableByteSpan & outNetworkIdentity)
     339              :     {
     340              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     341              :     }
     342              : 
     343              :     /**
     344              :      * @brief Retrieves the Network Client Identity associated with a network.
     345              :      *
     346              :      * @param networkIndex          The 0-based index of the network.
     347              :      * @param outNetworkIdentity    The output buffer to be populated with the Network
     348              :      *                              Client Identity in compact-pdc-identity TLV format.
     349              :      *
     350              :      * @return CHIP_NO_ERROR on success or a CHIP_ERROR on failure.
     351              :      */
     352              :     virtual CHIP_ERROR GetClientIdentity(uint8_t networkIndex, MutableByteSpan & outClientIdentity)
     353              :     {
     354              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     355              :     }
     356              : 
     357              :     /**
     358              :      * @brief Signs the specified message with the private key of a Network Client Identity.
     359              :      */
     360              :     virtual CHIP_ERROR SignWithClientIdentity(uint8_t networkIndex, const ByteSpan & message,
     361              :                                               Crypto::P256ECDSASignature & outSignature)
     362              :     {
     363              :         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
     364              :     }
     365              : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
     366              : 
     367              :     /**
     368              :      *  @brief Provide all the frequency bands supported by the Wi-Fi interface.
     369              :      *
     370              :      *  The default implementation returns the 2.4 GHz band support.
     371              :      *  Note: WiFi platforms should implement this function in their WiFiDriver to provide their complete device capabilities.
     372              :      *
     373              :      *  The returned bit mask has values of WiFiBandEnum packed into the bits. For example:
     374              :      *
     375              :      *    - Bit 0 = (WiFiBandEnum::k2g4 == 0) --> (1 << 0) == (1 << WiFiBandEnum::k2g4)
     376              :      *    - Bit 2 = (WiFiBandEnum::k5g == 2) --> (1 << 2) == (1 << WiFiBandEnum::k5g)
     377              :      *    - If both 2.4G and 5G are supported --> ((1 << k2g4) || (1 << k5g)) == (1 || 4) == 5
     378              :      *
     379              :      *  On error, return 0 (no bands supported). This should never happen... Note that
     380              :      *  certification tests will REQUIRE at least one bit set in the set.
     381              :      *
     382              :      *  @return a bitmask of supported Wi-Fi bands where each bit is associated with a WiFiBandEnum value.
     383              :      */
     384            0 :     virtual uint32_t GetSupportedWiFiBandsMask() const
     385              :     {
     386              :         // Default to 2.4G support (100% example platform coverage as of Matter 1.3) listed.
     387            0 :         return static_cast<uint32_t>(1UL << chip::to_underlying(WiFiBandEnum::k2g4));
     388              :     }
     389              : 
     390            2 :     ~WiFiDriver() override = default;
     391              : };
     392              : 
     393              : class ThreadDriver : public Internal::WirelessDriver
     394              : {
     395              : public:
     396              :     class ScanCallback
     397              :     {
     398              :     public:
     399              :         /**
     400              :          * Indicates the scan is finished, and accepts a iterator of networks discovered.
     401              :          * - networks can be nullptr when no networks discovered, or error occurred during scanning the networks.
     402              :          * OnFinished() must be called in a thread-safe manner with CHIP stack. (e.g. using ScheduleWork or ScheduleLambda)
     403              :          * - Users can assume the networks will always be used (and Release will be called) inside this function call. However, the
     404              :          * iterator might be not fully consumed (i.e. There are too many networks scanned to fit in the buffer for scan response
     405              :          * message.)
     406              :          */
     407              :         virtual void OnFinished(Status err, CharSpan debugText, ThreadScanResponseIterator * networks) = 0;
     408              : 
     409            2 :         virtual ~ScanCallback() = default;
     410              :     };
     411              : 
     412              :     /**
     413              :      * @brief Adds or updates a Thread network on the device. The driver should fill the outDebugText field to pass any
     414              :      * human-readable messages to the client. The driver should reduce the size of outDebugText to 0 to omit it from the response
     415              :      * when no debug text needs to be delivered. On success, the driver should set outNetworkIndex to the index of the network just
     416              :      * added or updated. The value of the network index is discarded on failure.
     417              :      *
     418              :      * Note: The capacity of outDebugText passed by network commissioning cluster can be configured via
     419              :      * CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE.
     420              :      */
     421              :     virtual Status AddOrUpdateNetwork(ByteSpan operationalDataset, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) = 0;
     422              : 
     423              :     /**
     424              :      * @brief Initializes a Thread network scan. callback->OnFinished must be called, on both success and error. Callback can
     425              :      * be called inside ScanNetworks.
     426              :      */
     427              :     virtual void ScanNetworks(ScanCallback * callback) = 0;
     428              : 
     429              :     /**
     430              :      * @brief Provide all of the Thread features supported by the Thread interface
     431              :      */
     432              :     virtual ThreadCapabilities GetSupportedThreadFeatures() = 0;
     433              : 
     434              :     /**
     435              :      * @brief Return the Thread version supported by the Thread interface
     436              :      */
     437              :     virtual uint16_t GetThreadVersion() = 0;
     438              : 
     439            0 :     ~ThreadDriver() override = default;
     440              : };
     441              : 
     442              : class EthernetDriver : public Internal::BaseDriver
     443              : {
     444              :     // Ethernet driver does not have any special operations.
     445              : };
     446              : 
     447              : } // namespace NetworkCommissioning
     448              : } // namespace DeviceLayer
     449              : } // namespace chip
        

Generated by: LCOV version 2.0-1