blob: 9a8c111100ed042f54e7632e954aebaeb01cf771 [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.
*/
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <platform/Beken/NetworkCommissioningDriver.h>
#include <platform/CHIPDeviceLayer.h>
#include <limits>
#include <string>
#include "wlan_ui_pub.h"
using namespace ::chip;
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
namespace chip {
namespace DeviceLayer {
namespace NetworkCommissioning {
namespace {
constexpr char kWiFiSSIDKeyName[] = "wifi-ssid";
constexpr char kWiFiCredentialsKeyName[] = "wifi-pass";
} // namespace
CHIP_ERROR BekenWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback)
{
CHIP_ERROR err;
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::Init\r\n");
err = GetSavedNetWorkConfig(&mSavedNetwork);
mStagingNetwork = mSavedNetwork;
mpScanCallback = nullptr;
mpConnectCallback = nullptr;
mpStatusChangeCallback = networkStatusChangeCallback;
return err;
}
CHIP_ERROR BekenWiFiDriver::GetSavedNetWorkConfig(WiFiNetwork * WifiNetconf)
{
CHIP_ERROR err;
size_t ssidLen = 0;
size_t credentialsLen = 0;
memset(WifiNetconf, 0x0, sizeof(WiFiNetwork));
err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, WifiNetconf->credentials,
sizeof(WifiNetconf->credentials), &credentialsLen);
if (err == CHIP_ERROR_NOT_FOUND)
{
return CHIP_NO_ERROR;
}
err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, WifiNetconf->ssid, sizeof(WifiNetconf->ssid), &ssidLen);
if (err == CHIP_ERROR_NOT_FOUND)
{
return CHIP_NO_ERROR;
}
WifiNetconf->credentialsLen = credentialsLen;
WifiNetconf->ssidLen = ssidLen;
return err;
}
void BekenWiFiDriver::Shutdown()
{
mpStatusChangeCallback = nullptr;
}
CHIP_ERROR BekenWiFiDriver::CommitConfiguration()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::CommitConfiguration\r\n");
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen));
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials,
mStagingNetwork.credentialsLen));
mSavedNetwork = mStagingNetwork;
return CHIP_NO_ERROR;
}
CHIP_ERROR BekenWiFiDriver::RevertConfiguration()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::RevertConfiguration\r\n");
mStagingNetwork = mSavedNetwork;
return CHIP_NO_ERROR;
}
bool BekenWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::NetworkMatch\r\n");
return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0;
}
Status BekenWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,
uint8_t & outNetworkIndex)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::AddOrUpdateNetwork\r\n");
outDebugText.reduce_size(0);
outNetworkIndex = 0;
VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded);
VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange);
VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange);
memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size());
mStagingNetwork.credentialsLen = static_cast<decltype(mStagingNetwork.credentialsLen)>(credentials.size());
memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size());
mStagingNetwork.ssidLen = static_cast<decltype(mStagingNetwork.ssidLen)>(ssid.size());
return Status::kSuccess;
}
Status BekenWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::RemoveNetwork\r\n");
outDebugText.reduce_size(0);
outNetworkIndex = 0;
VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
// Use empty ssid for representing invalid network
mStagingNetwork.ssidLen = 0;
return Status::kSuccess;
}
Status BekenWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ReorderNetwork\r\n");
// Only one network is supported now
outDebugText.reduce_size(0);
VerifyOrReturnError(index == 0, Status::kOutOfRange);
VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
return Status::kSuccess;
}
CHIP_ERROR BekenWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ConnectWiFiNetwork....ssid:%s", StringOrNullMarker(ssid));
ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled));
wifi_sta_config_t sta_config;
memset(&sta_config, 0x0, sizeof(sta_config));
sta_config.security = WIFI_SECURITY_AUTO; // can't use WIFI_DEFAULT_STA_CONFIG because of C99 designator error
Platform::CopyString(sta_config.ssid, ssidLen, ssid);
Platform::CopyString(sta_config.password, keyLen, key);
BK_LOG_ON_ERR(bk_wifi_sta_set_config(&sta_config));
BK_LOG_ON_ERR(bk_wifi_sta_start());
BK_LOG_ON_ERR(bk_wifi_sta_connect());
return ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled);
}
void BekenWiFiDriver::OnConnectWiFiNetwork()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnConnectWiFiNetwork\r\n");
if (mpConnectCallback)
{
// chip::DeviceLayer::PlatformMgr().LockChipStack();
mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0);
// chip::DeviceLayer::PlatformMgr().UnlockChipStack();
mpConnectCallback = nullptr;
}
}
void BekenWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ConnectNetwork\r\n");
CHIP_ERROR err = CHIP_NO_ERROR;
Status networkingStatus = Status::kSuccess;
VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound);
VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError);
err = ConnectWiFiNetwork(reinterpret_cast<const char *>(mStagingNetwork.ssid), mStagingNetwork.ssidLen,
reinterpret_cast<const char *>(mStagingNetwork.credentials), mStagingNetwork.credentialsLen);
mpConnectCallback = callback;
exit:
if (err != CHIP_NO_ERROR)
{
networkingStatus = Status::kUnknownError;
}
if (networkingStatus != Status::kSuccess)
{
ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network:%s", chip::ErrorStr(err));
mpConnectCallback = nullptr;
// chip::DeviceLayer::PlatformMgr().LockChipStack();
callback->OnResult(networkingStatus, CharSpan(), 0);
// chip::DeviceLayer::PlatformMgr().UnlockChipStack();
}
}
CHIP_ERROR GetConnectedNetwork(Network & network)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::GetConnectedNetwork\r\n");
wifi_link_status_t wifi_setting;
memset(&wifi_setting, 0x0, sizeof(wifi_setting));
bk_wifi_sta_get_link_status(&wifi_setting);
uint8_t length = strnlen(reinterpret_cast<const char *>(wifi_setting.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength);
os_memcpy(network.networkID, wifi_setting.ssid, length);
ChipLogProgress(NetworkProvisioning, "networkID:[%s][%d]\r\n", network.networkID, length);
network.networkIDLen = length;
return CHIP_NO_ERROR;
}
void BekenWiFiDriver::OnNetworkStatusChange()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnNetworkStatusChange\r\n");
Network configuredNetwork = { 0 };
VerifyOrReturn(mpStatusChangeCallback != nullptr);
GetConnectedNetwork(configuredNetwork);
if (configuredNetwork.networkIDLen)
{
mpStatusChangeCallback->OnNetworkingStatusChange(
Status::kSuccess, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), NullOptional);
return;
}
mpStatusChangeCallback->OnNetworkingStatusChange(
Status::kUnknownError, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)),
MakeOptional(GetLastDisconnectReason()));
}
CHIP_ERROR BekenWiFiDriver::SetLastDisconnectReason(const ChipDeviceEvent * event)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::SetLastDisconnectReason\r\n");
mLastDisconnectedReason = event->Platform.BKSystemEvent.Data.WiFiStaDisconnected;
return CHIP_NO_ERROR;
}
int32_t BekenWiFiDriver::GetLastDisconnectReason()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::GetLastDisconnectReason\r\n");
return mLastDisconnectedReason;
}
static beken_semaphore_t matter_scan_sema = NULL;
int scan_done_handler(void * arg, event_module_t event_module, int event_id, void * event_data)
{
if (matter_scan_sema)
{
rtos_set_semaphore(&matter_scan_sema);
}
return BK_OK;
}
CHIP_ERROR BekenWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::StartScanWiFiNetworks\r\n");
wifi_scan_config_t config = { 0 };
if (ssid.data() == NULL) // non-directed scanning
{
ChipLogProgress(NetworkProvisioning, "non-directed scanning...\r\n");
BK_LOG_ON_ERR(bk_wifi_scan_start(NULL));
}
else // directed scanning
{
os_memcpy(config.ssid, ssid.data(), ssid.size());
ChipLogProgress(NetworkProvisioning, "directed scanning... ssid:%s ; %d \r\n", config.ssid, ssid.size());
BK_LOG_ON_ERR(bk_wifi_scan_start(&config));
}
return CHIP_NO_ERROR;
}
void BekenWiFiDriver::OnScanWiFiNetworkDone()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnScanWiFiNetworkDone\r\n");
if (!GetInstance().mpScanCallback)
{
ChipLogProgress(NetworkProvisioning, "can't find the ScanCallback function\r\n");
return;
}
wifi_scan_result_t scan_result = { 0 };
int scan_rst_ap_num = 0;
BK_LOG_ON_ERR(bk_wifi_scan_get_result(&scan_result));
scan_rst_ap_num = scan_result.ap_num;
if (scan_rst_ap_num < 2) // beken scan result > = 1
{
ChipLogProgress(NetworkProvisioning, "NULL AP\r\n");
GetInstance().mpScanCallback->OnFinished(Status::kNetworkNotFound, CharSpan(), nullptr);
}
else
{
ChipLogProgress(NetworkProvisioning, "AP num = %d\r\n", scan_rst_ap_num);
BKScanResponseIterator iter(scan_rst_ap_num, &scan_result);
GetInstance().mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter);
}
GetInstance().mpScanCallback = nullptr;
bk_wifi_scan_free_result(&scan_result);
}
void BekenWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ScanNetworks\r\n");
if (callback != nullptr)
{
mpScanCallback = callback;
if (matter_scan_sema == NULL)
{
BK_LOG_ON_ERR(rtos_init_semaphore(&matter_scan_sema, 1));
}
BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_WIFI, EVENT_WIFI_SCAN_DONE, scan_done_handler, NULL));
if (StartScanWiFiNetworks(ssid) != CHIP_NO_ERROR)
{
mpScanCallback = nullptr;
callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
}
BK_LOG_ON_ERR(rtos_get_semaphore(&matter_scan_sema, 4000)); // timeout 4000ms
BK_LOG_ON_ERR(bk_event_unregister_cb(EVENT_MOD_WIFI, EVENT_WIFI_SCAN_DONE, scan_done_handler));
BK_LOG_ON_ERR(rtos_deinit_semaphore(&matter_scan_sema));
matter_scan_sema = NULL;
OnScanWiFiNetworkDone();
}
}
size_t BekenWiFiDriver::WiFiNetworkIterator::Count()
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::WiFiNetworkIterator::Count\r\n");
return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1;
}
bool BekenWiFiDriver::WiFiNetworkIterator::Next(Network & item)
{
ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::WiFiNetworkIterator::Next\r\n");
if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0)
{
return false;
}
uint8_t length =
strnlen(reinterpret_cast<const char *>(mDriver->mStagingNetwork.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength);
memcpy(item.networkID, mDriver->mStagingNetwork.ssid, length);
item.networkIDLen = length;
item.connected = false;
mExhausted = true;
Network connectedNetwork = { 0 };
CHIP_ERROR err = GetConnectedNetwork(connectedNetwork);
if (err == CHIP_NO_ERROR)
{
if (connectedNetwork.networkIDLen == item.networkIDLen &&
memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0)
{
item.connected = true;
}
}
return true;
}
} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI