| /* |
| * |
| * Copyright (c) 2022 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include <app-common/zap-generated/cluster-enums.h> |
| #include <app/icd/server/ICDServerConfig.h> |
| #include <platform/NetworkCommissioning.h> |
| |
| #include <array> |
| #include <cmsis_os2.h> |
| #include <lib/support/BitFlags.h> |
| #include <lib/support/Span.h> |
| #include <platform/silabs/wifi/WifiStateProvider.h> |
| #include <platform/silabs/wifi/icd/PowerSaveInterface.h> |
| #include <platform/silabs/wifi/wfx_msgs.h> |
| #include <sl_cmsis_os2_common.h> |
| #include <sl_status.h> |
| |
| #if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) |
| #include "rsi_common_apis.h" |
| #include "sl_si91x_types.h" |
| #include "sl_wifi_constants.h" |
| #include "sl_wifi_device.h" |
| #endif // (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) |
| |
| /* Updated constants */ |
| constexpr size_t kWiFiMacAddressLength = 6; |
| |
| /* Defines to update */ |
| #define MAX_JOIN_RETRIES_COUNT (5) |
| |
| using ScanCallback = void (*)(chip::DeviceLayer::NetworkCommissioning::WiFiScanResponse *); |
| |
| typedef struct wfx_wifi_scan_ext |
| { |
| uint32_t beacon_lost_count; |
| uint32_t beacon_rx_count; |
| uint32_t mcast_rx_count; |
| uint32_t mcast_tx_count; |
| uint32_t ucast_rx_count; |
| uint32_t ucast_tx_count; |
| uint32_t overrun_count; |
| } wfx_wifi_scan_ext_t; |
| |
| #ifdef SL_MATTER_SIWX_WIFI_ENABLE |
| /* |
| * This Sh%t is here to support WFXUtils - and the Matter stuff that uses it |
| * We took it from the SDK (for WF200) |
| */ |
| typedef enum |
| { |
| SL_WFX_STA_INTERFACE = 0, ///< Interface 0, linked to the station |
| SL_WFX_SOFTAP_INTERFACE = 1, ///< Interface 1, linked to the softap |
| } sl_wfx_interface_t; |
| #endif |
| |
| /* Updated section */ |
| |
| namespace chip { |
| namespace DeviceLayer { |
| namespace Silabs { |
| |
| /** |
| * @brief Public Interface for the Wi-Fi platform APIs |
| * |
| */ |
| class WifiInterface : public WifiStateProvider, public PowerSaveInterface |
| { |
| public: |
| enum class WifiEvent : uint8_t |
| { |
| kStartUp = 0, |
| kConnect = 1, |
| kDisconnect = 2, |
| kScanComplete = 3, |
| kGotIPv4 = 4, |
| kGotIPv6 = 5, |
| kLostIP = 6, |
| }; |
| |
| enum class WifiState : uint16_t |
| { |
| kStationInit = (1 << 0), |
| kAPReady = (1 << 1), |
| kStationProvisioned = (1 << 2), |
| kStationConnecting = (1 << 3), |
| kStationConnected = (1 << 4), |
| kStationDhcpDone = (1 << 6), /* Requested to do DHCP after conn */ |
| kStationMode = (1 << 7), /* Enable Station Mode */ |
| kAPMode = (1 << 8), /* Enable AP Mode */ |
| kStationReady = (kStationConnected | kStationDhcpDone), |
| kStationStarted = (1 << 9), |
| kScanStarted = (1 << 10), /* Scan Started */ |
| }; |
| |
| enum class WifiDisconnectionReasons : uint16_t // using uint16 to match current structure during the transition |
| { |
| kUnknownError = 1, // Disconnation due to an internal error |
| kAccessPointLost = 2, // Device did not receive AP beacon too many times |
| kAccessPoint = 3, // AP disconnected the device |
| kApplication = 4, // Application requested disconnection |
| kWPACouterMeasures = 5, // WPA contermeasures triggered a disconnection |
| }; |
| |
| struct WiFiCredentials |
| { |
| WiFiCredentials() { Clear(); } |
| |
| uint8_t ssid[chip::DeviceLayer::Internal::kMaxWiFiSSIDLength] = { 0 }; |
| size_t ssidLen = 0; |
| |
| uint8_t key[chip::DeviceLayer::Internal::kMaxWiFiKeyLength] = { 0 }; |
| size_t keyLen = 0; |
| |
| chip::BitFlags<chip::app::Clusters::NetworkCommissioning::WiFiSecurityBitmap> security; |
| |
| WiFiCredentials & operator=(const WiFiCredentials & other) |
| { |
| if (this != &other) |
| { |
| memcpy(ssid, other.ssid, chip::DeviceLayer::Internal::kMaxWiFiSSIDLength); |
| ssidLen = other.ssidLen; |
| |
| memcpy(key, other.key, chip::DeviceLayer::Internal::kMaxWiFiKeyLength); |
| keyLen = other.keyLen; |
| |
| security = other.security; |
| } |
| return *this; |
| } |
| |
| void Clear() |
| { |
| memset(ssid, 0, chip::DeviceLayer::Internal::kMaxWiFiSSIDLength); |
| ssidLen = 0; |
| |
| memset(key, 0, chip::DeviceLayer::Internal::kMaxWiFiKeyLength); |
| keyLen = 0; |
| |
| security.ClearAll(); |
| } |
| }; |
| |
| using MacAddress = std::array<uint8_t, kWiFiMacAddressLength>; |
| |
| virtual ~WifiInterface() = default; |
| |
| /** |
| * @brief Returns the singleton instance of the WiFi interface |
| * |
| * @note This function needs to be implemented in the child classes sources file |
| * |
| * @return WifiInterface& |
| */ |
| static WifiInterface & GetInstance(); |
| |
| /** |
| * @brief Function initalizes the WiFi module before starting the WiFi task. |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR, if the initialization succeeded |
| * CHIP_ERROR_INTERNAL, if sequence failed due to internal API error |
| * CHIP_ERROR_NO_MEMORY, if sequence failed due to unavaliablility of memory |
| */ |
| |
| virtual CHIP_ERROR InitWiFiStack(void) = 0; |
| |
| /** |
| * @brief Returns the provide interfaces MAC address |
| * Valid buffer large enough for the MAC address must be provided to the function |
| * |
| * @param[in] interface SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE. |
| * If soft AP is not enabled, the interface is ignored and the function always returns the Station MAC |
| * address |
| * @param[out] addr Interface MAC addres |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR on success |
| * CHIP_ERROR_BUFFER_TOO_SMALL if the provided ByteSpan size is too small |
| * |
| */ |
| virtual CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr) = 0; |
| |
| /** |
| * @brief Triggers a network scan |
| * The function is asynchronous and the result is provided via the callback. |
| * |
| * @param ssid The SSID to scan for. If empty, all networks are scanned |
| * @param callback The callback to be called when the scan is complete. Cannot be nullptr. |
| * The callback is called asynchrounously. |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR if the network scan was successfully started |
| * CHIP_INVALID_ARGUMENT if the callback is nullptr |
| * CHIP_ERROR_IN_PROGRESS, if there is already a network scan in progress |
| * CHIP_ERROR_INVALID_STRING_LENGTH, if there SSID length exceeds handled limit |
| * other, if there is a platform error when starting the scan |
| */ |
| virtual CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) = 0; |
| |
| /** |
| * @brief Creates and starts the WiFi task that processes Wifi events and operations |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR if the task was successfully started and initialized |
| * CHIP_ERROR_NO_MEMORY if the task failed to be created |
| * CHIP_ERROR_INTERNAL if software or hardware initialization failed |
| */ |
| virtual CHIP_ERROR StartWifiTask() = 0; |
| |
| /** |
| * @brief Configures the Wi-Fi devices as a Wi-Fi station |
| */ |
| virtual void ConfigureStationMode() = 0; |
| |
| /** |
| * @brief Triggers the device to disconnect from the connected Wi-Fi network |
| * |
| * @note The disconnection is not immediate. It can take a certain amount of time for the device to be in a disconnected state |
| * once the function is called. When the function returns, the device might not have yet disconnected from the Wi-Fi network. |
| * The implementation may only enqueue a disconnect (e.g. post an event); there is no synchronous success/failure to report. |
| */ |
| virtual void TriggerDisconnection() = 0; |
| |
| /** |
| * @brief Gets the connected access point information. |
| * See @NetworkCommissioning::WiFiScanResponse for the information that is returned by the function. |
| * |
| * @param[out] info AP information |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information |
| * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. |
| */ |
| virtual CHIP_ERROR GetAccessPointInfo(chip::DeviceLayer::NetworkCommissioning::WiFiScanResponse & info) = 0; |
| |
| /** |
| * @brief Gets the connected access point extended information. |
| * See @wfx_wifi_scan_ext_t for the information that is returned by the information |
| * |
| * @param[out] info AP extended information |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information |
| * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. |
| */ |
| virtual CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) = 0; |
| |
| /** |
| * @brief Function resets the BeaconLostCount, BeaconRxCount, PacketMulticastRxCount, PacketMulticastTxCount, |
| * PacketUnicastRxCount, PacketUnicastTxCount back to 0 |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR, the counters were succesfully reset to 0. |
| * CHIP_ERROR_INTERNAL, if there was an error when resetting the counter values |
| */ |
| virtual CHIP_ERROR ResetCounters() = 0; |
| |
| /** |
| * @brief Clears the stored Wi-Fi crendetials stored in RAM only |
| */ |
| virtual void ClearWifiCredentials() = 0; |
| |
| /** |
| * @brief Stores the Wi-Fi credentials |
| * |
| * @note Function does not validate if the device already has Wi-Fi credentials. |
| * It is the responsibility of the caller to ensuret that. |
| * The function will overwrite any existing Wi-Fi credentials. |
| * |
| * @param[in] credentials |
| * @return CHIP_ERROR CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if ssidLength is 0 or exceeds max SSID length |
| */ |
| virtual CHIP_ERROR SetWifiCredentials(const WiFiCredentials & credentials) = 0; |
| |
| /** |
| * @brief Returns the configured Wi-Fi credentials |
| * |
| * @param[out] credentials stored wifi crendetials |
| * |
| * @return CHIP_ERROR CHIP_ERROR_INCORRECT_STATE, if the device does not have any set credentials |
| * CHIP_NO_ERROR, otherwise |
| */ |
| virtual CHIP_ERROR GetWifiCredentials(WiFiCredentials & credentials) = 0; |
| |
| /** |
| * @brief Triggers a connection attempt the Access Point who's credentials match the ones store with the SetWifiCredentials API. |
| * The function triggers an async connection attempt. The upper layers are notified trought a platform event if the |
| * connection attempt was successful or not. |
| * |
| * The returned error code only indicates if the connection attempt was triggered or not. |
| * On retry after failure, the implementation may use quick join (no scan) when channel/BSSID are known. |
| * |
| * @return CHIP_ERROR CHIP_NO_ERROR, the connection attempt was succesfully triggered |
| * CHIP_ERROR_INCORRECT_STATE, the Wi-Fi station does not have any Wi-Fi credentials |
| * CHIP_ERROR_INVALID_ARGUMENT, the provisionned crendetials do not match the Wi-Fi station requirements |
| * CHIP_ERROR_INTERNAL, otherwise |
| */ |
| virtual CHIP_ERROR ConnectToAccessPoint(void) = 0; |
| |
| /** |
| * @brief Cancels the on-going network scan operation. |
| * If one isn't in-progress, function doesn't do anything |
| */ |
| virtual void CancelScanNetworks() = 0; |
| |
| /** |
| * @brief Provide all the frequency bands supported by the Wi-Fi interface. |
| * |
| * The default implementation returns the 2.4 GHz band support. |
| * |
| * @return a bitmask of supported Wi-Fi bands where each bit is associated with a WiFiBandEnum value. |
| */ |
| virtual uint32_t GetSupportedWiFiBandsMask() const |
| { |
| // Default to 2.4G support only |
| return static_cast<uint32_t>(1UL << chip::to_underlying(chip::app::Clusters::NetworkCommissioning::WiFiBandEnum::k2g4)); |
| } |
| |
| /** |
| * @brief Function resets reconnection attempt interval back to the minimum value |
| */ |
| void ResetConnectionRetryInterval(); |
| |
| protected: |
| /** |
| * @brief Function notifies the PlatformManager that an IPv6 event occured on the WiFi interface. |
| * |
| * @param gotIPv6Addr true, got an IPv6 address |
| * false, lost or wasn't able to get an IPv6 address |
| */ |
| void NotifyIPv6Change(bool gotIPv6Addr); |
| |
| #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 |
| /** |
| * @brief Updates the IPv4 address in the Wi-Fi interface and notifies the application layer about the new IP address. |
| * |
| * @param[in] ip New IPv4 address |
| */ |
| void GotIPv4Address(uint32_t ip); |
| /** |
| * @brief Function notifies the PlatformManager that an IPv4 event occured on the WiFi interface. |
| * |
| * @param gotIPv4Addr true, got an IPv4 address |
| * false, lost or wasn't able to get an IPv4 address |
| */ |
| void NotifyIPv4Change(bool gotIPv4Addr); |
| #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ |
| |
| /** |
| * @brief Function notifies the PlatformManager that a disconnection event occurred |
| * |
| * @param reason reason for the disconnection |
| */ |
| void NotifyDisconnection(WifiDisconnectionReasons reason); |
| |
| /** |
| * @brief Function notifies the PlatformManager that a connection event occurred |
| * |
| * @param[in] ap pointer to the structure that contains the MAC address of the AP |
| */ |
| void NotifyConnection(const MacAddress & ap); |
| |
| /** |
| * @brief Function resets the IP notification states |
| * |
| */ |
| void ResetIPNotificationStates(); |
| |
| /** |
| * @brief Notifies upper-layers that Wi-Fi initialization has succesfully completed |
| */ |
| void NotifyWifiTaskInitialized(void); |
| |
| /** |
| * @brief Function schedules a reconnection attempt with the Access Point |
| * |
| * @note The retry interval increases exponentially with each attempt, starting from a minimum value and doubling each time, |
| * up to a maximum value. For example, if the initial retry interval is 1 second, the subsequent intervals will be 2 |
| * seconds, 4 seconds, 8 seconds, and so on, until the maximum retry interval is reached. |
| */ |
| void ScheduleConnectionAttempt(); |
| |
| bool mHasNotifiedIPv6 = false; |
| #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 |
| bool mHasNotifiedIPv4 = false; |
| #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 |
| |
| private: |
| osTimerId_t mRetryTimer; |
| }; |
| |
| } // namespace Silabs |
| } // namespace DeviceLayer |
| } // namespace chip |
| |
| // TODO: This structure can be split into members of the interfaces |
| // This needs to be after the class definition since it depends on class members |
| typedef struct wfx_rsi_s |
| { |
| chip::BitFlags<chip::DeviceLayer::Silabs::WifiInterface::WifiState> dev_state; |
| uint16_t ap_chan; /* The chan our STA is using */ |
| chip::DeviceLayer::Silabs::WifiInterface::WiFiCredentials credentials; |
| ScanCallback scan_cb; |
| #ifdef SL_WFX_CONFIG_SOFTAP |
| chip::DeviceLayer::Silabs::WifiInterface::MacAddress softap_mac; |
| #endif |
| chip::DeviceLayer::Silabs::WifiInterface::MacAddress sta_mac; |
| chip::DeviceLayer::Silabs::WifiInterface::MacAddress ap_mac; /* To which our STA is connected */ |
| chip::DeviceLayer::Silabs::WifiInterface::MacAddress ap_bssid; /* To which our STA is connected */ |
| uint8_t ip4_addr[4]; /* Not sure if this is enough */ |
| } WfxRsi_t; |