blob: 430b9bbddb7d38e1394e3b82f647f33b1774a513 [file] [log] [blame]
/*
*
* 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.
*/
// SL MATTER WI-FI INTERFACE
#include "silabs_utils.h"
#include <app/icd/server/ICDServerConfig.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/silabs/wifi/WifiInterfaceAbstraction.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace chip;
using namespace chip::DeviceLayer;
#define CONVERT_SEC_TO_MS(TimeInS) (TimeInS * 1000)
// TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation.
// As such we can't depend on the platform here as well
extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData);
namespace {
constexpr uint8_t kWlanMinRetryIntervalsInSec = 1;
constexpr uint8_t kWlanMaxRetryIntervalsInSec = 60;
constexpr uint8_t kWlanRetryIntervalInSec = 5;
uint8_t retryInterval = kWlanMinRetryIntervalsInSec;
osTimerId_t sRetryTimer;
/*
* Notifications to the upper-layer
* All done in the context of the RSI/WiFi task (rsi_if.c)
*/
void RetryConnectionTimerHandler(void * arg)
{
#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE
wfx_rsi_power_save(RSI_ACTIVE, HIGH_PERFORMANCE);
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE
if (wfx_connect_to_ap() != SL_STATUS_OK)
{
ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed.");
}
}
} // namespace
/***********************************************************************************
* @fn sl_matter_wifi_task_started(void)
* @brief
* Wifi device started notification
* @param[in]: None
* @return None
*************************************************************************************/
void sl_matter_wifi_task_started(void)
{
sl_wfx_startup_ind_t evt;
sl_wfx_mac_address_t mac;
// Creating a timer which will be used to retry connection with AP
sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL);
VerifyOrReturn(sRetryTimer != NULL);
memset(&evt, 0, sizeof(evt));
evt.header.id = SL_WFX_STARTUP_IND_ID;
evt.header.length = sizeof evt;
evt.body.status = 0;
wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac);
memcpy(&evt.body.mac_addr[0], &mac.octet[0], MAC_ADDRESS_FIRST_OCTET);
HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
}
/***********************************************************************************
* @fn void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t *ap)
* @brief
* For now we are not notifying anything other than AP Mac -
* Other stuff such as DTIM etc. may be required for later
* @param[in] status:
* @param[in] ap: access point
* @return None
*************************************************************************************/
void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap)
{
sl_wfx_connect_ind_t evt;
VerifyOrReturn(status == SUCCESS_STATUS);
memset(&evt, 0, sizeof(evt));
evt.header.id = SL_WFX_CONNECT_IND_ID;
evt.header.length = sizeof evt;
#ifdef RS911X_WIFI
evt.body.channel = wfx_rsi.ap_chan;
#endif
memcpy(&evt.body.mac[0], &ap->octet[0], MAC_ADDRESS_FIRST_OCTET);
HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
}
/**************************************************************************************
* @fn void wfx_disconnected_notify(int32_t status)
* @brief
* notification of disconnection
* @param[in] status:
* @return None
*************************************************************************************/
void wfx_disconnected_notify(int32_t status)
{
sl_wfx_disconnect_ind_t evt;
memset(&evt, 0, sizeof(evt));
evt.header.id = SL_WFX_DISCONNECT_IND_ID;
evt.header.length = sizeof evt;
evt.body.reason = status;
HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
}
/**************************************************************************************
* @fn void wfx_ipv6_notify(int got_ip)
* @brief
* notification of ipv6
* @param[in] got_ip:
* @return None
*************************************************************************************/
void wfx_ipv6_notify(int got_ip)
{
sl_wfx_generic_message_t eventData;
memset(&eventData, 0, sizeof(eventData));
eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP;
eventData.header.length = sizeof(eventData.header);
HandleWFXSystemEvent(IP_EVENT, &eventData);
}
/**************************************************************************************
* @fn void wfx_ip_changed_notify(int got_ip)
* @brief
* notification of ip change
* @param[in] got_ip:
* @return None
*************************************************************************************/
void wfx_ip_changed_notify(int got_ip)
{
sl_wfx_generic_message_t eventData;
memset(&eventData, 0, sizeof(eventData));
eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP;
eventData.header.length = sizeof(eventData.header);
HandleWFXSystemEvent(IP_EVENT, &eventData);
}
/**************************************************************************************
* @fn void wfx_retry_connection(uint16_t retryAttempt)
* @brief
* During commissioning, we retry to join the network MAX_JOIN_RETRIES_COUNT times.
* If DUT is disconnected from the AP or device is power cycled, then retry connection
* with AP continously after a certain time interval.
* @param[in] retryAttempt
* @return None
*************************************************************************************/
void wfx_retry_connection(uint16_t retryAttempt)
{
// During commissioning, we retry to join the network MAX_JOIN_RETRIES_COUNT
if (/*BaseApplication::sAppDelegate.isCommissioningInProgress()*/ true)
{
if (retryAttempt < MAX_JOIN_RETRIES_COUNT)
{
ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", kWlanRetryIntervalInSec);
if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(kWlanRetryIntervalInSec))) != osOK)
{
ChipLogProgress(DeviceLayer, "Failed to start retry timer");
// Sending the join command if retry timer failed to start
if (wfx_connect_to_ap() != SL_STATUS_OK)
{
ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed.");
}
return;
}
}
else
{
ChipLogProgress(DeviceLayer, "Connect failed after max %d tries", retryAttempt);
}
}
else
{
/* After disconnection or power cycle the DUT
* At the telescopic time interval device try to reconnect with AP, upto WLAN_MAX_RETRY_TIMER_MS intervals
* are telescopic. If interval exceed WLAN_MAX_RETRY_TIMER_MS then it will try to reconnect at
* WLAN_MAX_RETRY_TIMER_MS intervals.
*/
if (retryInterval > kWlanMaxRetryIntervalsInSec)
{
retryInterval = kWlanMaxRetryIntervalsInSec;
}
if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(retryInterval))) != osOK)
{
ChipLogProgress(DeviceLayer, "Failed to start retry timer");
// Sending the join command if retry timer failed to start
if (wfx_connect_to_ap() != SL_STATUS_OK)
{
ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed.");
}
return;
}
#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE
wfx_rsi_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION);
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE
ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", retryInterval);
retryInterval += retryInterval;
return;
}
}