diff --git a/src/platform/Tizen/BLEManagerImpl.cpp b/src/platform/Tizen/BLEManagerImpl.cpp index 3749d1d6f5027e..0846da66441913 100644 --- a/src/platform/Tizen/BLEManagerImpl.cpp +++ b/src/platform/Tizen/BLEManagerImpl.cpp @@ -500,7 +500,9 @@ void BLEManagerImpl::OnChipDeviceScanned(void * device, const Ble::ChipBLEDevice /* Set CHIP Connecting state */ mBLEScanConfig.mBleScanState = BleScanState::kConnecting; + chip::DeviceLayer::PlatformMgr().LockChipStack(); DeviceLayer::SystemLayer().StartTimer(kConnectTimeout, HandleConnectionTimeout, nullptr); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); mDeviceScanner->StopChipScan(); /* Initiate Connect */ diff --git a/src/platform/Tizen/NetworkCommissioningDriver.h b/src/platform/Tizen/NetworkCommissioningDriver.h index b9605c34e2b7a6..6654cbd0dc7930 100644 --- a/src/platform/Tizen/NetworkCommissioningDriver.h +++ b/src/platform/Tizen/NetworkCommissioningDriver.h @@ -26,6 +26,33 @@ namespace chip { namespace DeviceLayer { namespace NetworkCommissioning { +template +class TizenScanResponseIterator : public Iterator +{ +public: + TizenScanResponseIterator(std::vector * apScanResponse) : mpScanResponse(apScanResponse) {} + size_t Count() override { return mpScanResponse != nullptr ? mpScanResponse->size() : 0; } + bool Next(T & item) override + { + if (mpScanResponse == nullptr || currentIterating >= mpScanResponse->size()) + { + return false; + } + item = (*mpScanResponse)[currentIterating]; + currentIterating++; + return true; + } + void Release() override + { /* nothing to do, we don't hold the ownership of the vector, and users is not expected to hold the ownership in OnFinished for + scan. */ + } + +private: + size_t currentIterating = 0; + // Note: We cannot post a event in ScheduleLambda since std::vector is not trivial copyable. + std::vector * mpScanResponse; +}; + #if CHIP_DEVICE_CONFIG_ENABLE_WIFI class TizenWiFiDriver final : public WiFiDriver { diff --git a/src/platform/Tizen/NetworkCommissioningWiFiDriver.cpp b/src/platform/Tizen/NetworkCommissioningWiFiDriver.cpp index 02b03ac81dd1ae..48658321a6dc0e 100644 --- a/src/platform/Tizen/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/Tizen/NetworkCommissioningWiFiDriver.cpp @@ -161,19 +161,41 @@ void TizenWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callb void TizenWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) { - ChipLogError(NetworkProvisioning, "Not implemented"); + CHIP_ERROR err = DeviceLayer::Internal::WiFiMgr().StartWiFiScan(ssid, callback); + if (err != CHIP_NO_ERROR) + { + callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + } } size_t TizenWiFiDriver::WiFiNetworkIterator::Count() { - ChipLogError(NetworkProvisioning, "Not implemented"); - return 0; + return driver->mStagingNetwork.ssidLen == 0 ? 0 : 1; } bool TizenWiFiDriver::WiFiNetworkIterator::Next(Network & item) { - ChipLogError(NetworkProvisioning, "Not implemented"); - return false; + if (exhausted || driver->mStagingNetwork.ssidLen == 0) + { + return false; + } + memcpy(item.networkID, driver->mStagingNetwork.ssid, driver->mStagingNetwork.ssidLen); + item.networkIDLen = driver->mStagingNetwork.ssidLen; + item.connected = false; + exhausted = true; + + Network configuredNetwork; + CHIP_ERROR err = DeviceLayer::Internal::WiFiMgr().GetConfiguredNetwork(configuredNetwork); + if (err == CHIP_NO_ERROR) + { + if (DeviceLayer::Internal::WiFiMgr().IsWiFiStationConnected() && configuredNetwork.networkIDLen == item.networkIDLen && + memcmp(configuredNetwork.networkID, item.networkID, item.networkIDLen) == 0) + { + item.connected = true; + } + } + + return true; } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI diff --git a/src/platform/Tizen/WiFiManager.cpp b/src/platform/Tizen/WiFiManager.cpp index b6a8c09be7c22b..b13657e0d66c03 100644 --- a/src/platform/Tizen/WiFiManager.cpp +++ b/src/platform/Tizen/WiFiManager.cpp @@ -30,6 +30,9 @@ #include #include #include +#include + +using namespace ::chip::DeviceLayer::NetworkCommissioning; namespace { static constexpr const char * __WiFiDeviceStateToStr(wifi_manager_device_state_e state) @@ -129,6 +132,128 @@ static constexpr const char * __WiFiSecurityTypeToStr(wifi_manager_security_type return "(unknown)"; } } + +// wifi_manager's scan results don't contains the channel infomation, so we need this lookup table for resolving the band and +// channel infomation. +std::pair _GetBandAndChannelFromFrequency(int freq) +{ + std::pair ret = std::make_pair(WiFiBand::k2g4, 0); + if (freq <= 931) + { + ret.first = WiFiBand::k1g; + if (freq >= 916) + { + ret.second = ((freq - 916) * 2) - 1; + } + else if (freq >= 902) + { + ret.second = (freq - 902) * 2; + } + else if (freq >= 863) + { + ret.second = (freq - 863) * 2; + } + else + { + ret.second = 1; + } + } + else if (freq <= 2472) + { + ret.second = static_cast((freq - 2412) / 5 + 1); + } + else if (freq == 2484) + { + ret.second = 14; + } + else if (freq >= 3600 && freq <= 3700) + { + ret.first = WiFiBand::k3g65; + } + else if (freq >= 5035 && freq <= 5945) + { + ret.first = WiFiBand::k5g; + ret.second = static_cast((freq - 5000) / 5); + } + else if (freq == 5960 || freq == 5980) + { + ret.first = WiFiBand::k5g; + ret.second = static_cast((freq - 5000) / 5); + } + else if (freq >= 5955) + { + ret.first = WiFiBand::k6g; + ret.second = static_cast((freq - 5950) / 5); + } + else if (freq >= 58000) + { + ret.first = WiFiBand::k60g; + switch (freq) + { + case 58'320: + ret.second = 1; + break; + case 60'480: + ret.second = 2; + break; + case 62'640: + ret.second = 3; + break; + case 64'800: + ret.second = 4; + break; + case 66'960: + ret.second = 5; + break; + case 69'120: + ret.second = 6; + break; + case 59'400: + ret.second = 9; + break; + case 61'560: + ret.second = 10; + break; + case 63'720: + ret.second = 11; + break; + case 65'880: + ret.second = 12; + break; + case 68'040: + ret.second = 13; + break; + } + } + return ret; +} + +uint8_t _GetNetworkSecurityType(wifi_manager_security_type_e type) +{ + switch (type) + { + case WIFI_MANAGER_SECURITY_TYPE_NONE: + return 0x1; + case WIFI_MANAGER_SECURITY_TYPE_WEP: + return 0x2; + case WIFI_MANAGER_SECURITY_TYPE_WPA_PSK: + return 0x4; + case WIFI_MANAGER_SECURITY_TYPE_WPA2_PSK: + return 0x8; + case WIFI_MANAGER_SECURITY_TYPE_EAP: + return 0x10; + case WIFI_MANAGER_SECURITY_TYPE_WPA_FT_PSK: + return 0x10; + case WIFI_MANAGER_SECURITY_TYPE_SAE: + return 0x10; + case WIFI_MANAGER_SECURITY_TYPE_OWE: + return 0x10; + case WIFI_MANAGER_SECURITY_TYPE_DPP: + return 0x10; + default: + return 0x0; + } +} } // namespace namespace chip { @@ -199,7 +324,7 @@ void WiFiManager::_DeactivateCb(wifi_manager_error_e wifiErr, void * userData) } } -void WiFiManager::_ScanFinishedCb(wifi_manager_error_e wifiErr, void * userData) +void WiFiManager::_ScanToConnectFinishedCb(wifi_manager_error_e wifiErr, void * userData) { wifi_manager_ap_h foundAp = nullptr; @@ -219,6 +344,84 @@ void WiFiManager::_ScanFinishedCb(wifi_manager_error_e wifiErr, void * userData) } } +void WiFiManager::_ScanFinishedCb(wifi_manager_error_e wifiErr, void * userData) +{ + if (wifiErr == WIFI_MANAGER_ERROR_NONE) + { + std::vector networkScanned; + int err = wifi_manager_foreach_found_specific_ap(sInstance.mWiFiManagerHandle, _FoundAPOnScanCb, &networkScanned); + + VerifyOrReturn(err == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "FAIL: get scan list [%s]", get_error_message(err))); + + chip::DeviceLayer::PlatformMgr().LockChipStack(); + if (sInstance.mpScanCallback != nullptr) + { + TizenScanResponseIterator iter(&networkScanned); + sInstance.mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter); + sInstance.mpScanCallback = nullptr; + } + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + } + else + { + ChipLogError(DeviceLayer, "FAIL: scan WiFi [%s]", get_error_message(wifiErr)); + } +} + +bool WiFiManager::_FoundAPOnScanCb(wifi_manager_ap_h ap, void * userData) +{ + bool cbRet = true; + int wifiErr = WIFI_MANAGER_ERROR_NONE; + char * essid = nullptr; + char * bssid = nullptr; + int rssi = 0; + int freq = 0; + + auto networkScanned = static_cast *>(userData); + std::pair bandInfo; + + wifi_manager_security_type_e type; + WiFiScanResponse scannedAP; + + wifiErr = wifi_manager_ap_get_essid(ap, &essid); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "FAIL: get AP essid [%s]", get_error_message(wifiErr))); + ChipLogProgress(DeviceLayer, "Essid Found: %s\n", essid); + scannedAP.ssidLen = static_cast(std::min(strlen(essid), sizeof(scannedAP.ssid))); + memcpy(scannedAP.ssid, essid, scannedAP.ssidLen); + + wifiErr = wifi_manager_ap_get_bssid(ap, &bssid); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "Fail: get AP bssid [%s]", get_error_message(wifiErr))); + memcpy(scannedAP.bssid, bssid, std::min(strlen(bssid), sizeof(scannedAP.bssid))); + + wifiErr = wifi_manager_ap_get_rssi(ap, &rssi); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "Fail: get rssi value [%s]", get_error_message(wifiErr))); + scannedAP.rssi = static_cast(rssi); + + wifiErr = wifi_manager_ap_get_security_type(ap, &type); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "Fail: get AP security type [%s]", get_error_message(wifiErr))); + scannedAP.security.SetRaw(_GetNetworkSecurityType(type)); + + wifiErr = wifi_manager_ap_get_frequency(ap, &freq); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, + ChipLogError(DeviceLayer, "Fail: get AP frequency [%s]", get_error_message(wifiErr))); + bandInfo = _GetBandAndChannelFromFrequency(freq); + scannedAP.wiFiBand = bandInfo.first; + scannedAP.channel = static_cast(bandInfo.second); + + networkScanned->push_back(scannedAP); + +exit : { + g_free(essid); + g_free(bssid); +} + return cbRet; +} + bool WiFiManager::_FoundAPCb(wifi_manager_ap_h ap, void * userData) { bool cbRet = true; @@ -362,11 +565,23 @@ CHIP_ERROR WiFiManager::_WiFiDeactivate(gpointer userData) return CHIP_NO_ERROR; } +CHIP_ERROR WiFiManager::_WiFiScanToConnect(gpointer userData) +{ + int wifiErr; + + wifiErr = wifi_manager_scan(sInstance.mWiFiManagerHandle, _ScanToConnectFinishedCb, nullptr); + VerifyOrReturnError(wifiErr == WIFI_MANAGER_ERROR_NONE, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "FAIL: request WiFi scan [%s]", get_error_message(wifiErr))); + + ChipLogProgress(DeviceLayer, "WiFi scan is requested"); + return CHIP_NO_ERROR; +} + CHIP_ERROR WiFiManager::_WiFiScan(gpointer userData) { int wifiErr; - wifiErr = wifi_manager_scan(sInstance.mWiFiManagerHandle, _ScanFinishedCb, nullptr); + wifiErr = wifi_manager_scan_specific_ap(sInstance.mWiFiManagerHandle, sInstance.mInterestedSSID, _ScanFinishedCb, nullptr); VerifyOrReturnError(wifiErr == WIFI_MANAGER_ERROR_NONE, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "FAIL: request WiFi scan [%s]", get_error_message(wifiErr))); @@ -651,7 +866,7 @@ CHIP_ERROR WiFiManager::Connect(const char * ssid, const char * key, } else { - err = PlatformMgrImpl().GLibMatterContextInvokeSync(_WiFiScan, static_cast(nullptr)); + err = PlatformMgrImpl().GLibMatterContextInvokeSync(_WiFiScanToConnect, static_cast(nullptr)); SuccessOrExit(err); } @@ -694,6 +909,33 @@ CHIP_ERROR WiFiManager::Disconnect(const char * ssid) return err; } +CHIP_ERROR WiFiManager::StartWiFiScan(ByteSpan ssid, DeviceLayer::NetworkCommissioning::WiFiDriver::ScanCallback * callback) +{ + // If there is another ongoing scan request, reject the new one. + VerifyOrReturnError(sInstance.mpScanCallback == nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(ssid.size() <= sizeof(sInstance.mInterestedSSID) - 1, CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ERROR err = CHIP_NO_ERROR; + int wifiErr = WIFI_MANAGER_ERROR_NONE; + bool isWiFiActivated = false; + + memcpy(sInstance.mInterestedSSID, ssid.data(), ssid.size()); + sInstance.mInterestedSSID[ssid.size()] = '\0'; + + wifiErr = wifi_manager_is_activated(sInstance.mWiFiManagerHandle, &isWiFiActivated); + VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, err = CHIP_ERROR_INCORRECT_STATE; + ChipLogError(DeviceLayer, "FAIL: check whether WiFi is activated [%s]", get_error_message(wifiErr))); + + VerifyOrExit(isWiFiActivated == true, ChipLogProgress(DeviceLayer, "WiFi is deactivated")); + + sInstance.mpScanCallback = callback; + err = PlatformMgrImpl().GLibMatterContextInvokeSync(_WiFiScan, static_cast(nullptr)); + SuccessOrExit(err); + +exit: + return err; +} + CHIP_ERROR WiFiManager::RemoveAllConfigs() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -877,6 +1119,38 @@ CHIP_ERROR WiFiManager::GetSecurityType(wifi_manager_security_type_e * securityT return CHIP_NO_ERROR; } +CHIP_ERROR WiFiManager::GetConfiguredNetwork(NetworkCommissioning::Network & network) +{ + wifi_manager_ap_h connectedAp = _WiFiGetConnectedAP(); + if (connectedAp == nullptr) + { + return CHIP_ERROR_INCORRECT_STATE; + } + char * essid = nullptr; + int wifiErr = wifi_manager_ap_get_essid(connectedAp, &essid); + VerifyOrReturnError(wifiErr == WIFI_MANAGER_ERROR_NONE, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "FAIL: get essid [%s]", get_error_message(wifiErr))); + network.networkIDLen = static_cast(std::min(strlen(essid), sizeof(network.networkID))); + memcpy(network.networkID, essid, network.networkIDLen); + g_free(essid); + + return CHIP_NO_ERROR; +} + +bool WiFiManager::IsWiFiStationConnected() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + wifi_manager_connection_state_e connectionState = WIFI_MANAGER_CONNECTION_STATE_DISCONNECTED; + bool isWiFiStationConnected = false; + + err = GetConnectionState(&connectionState); + VerifyOrReturnError(err == CHIP_NO_ERROR, isWiFiStationConnected); + + if (connectionState == WIFI_MANAGER_CONNECTION_STATE_CONNECTED) + isWiFiStationConnected = true; + + return isWiFiStationConnected; +} } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Tizen/WiFiManager.h b/src/platform/Tizen/WiFiManager.h index 4ec6dec2e5d7aa..b9b21bb6ab761a 100644 --- a/src/platform/Tizen/WiFiManager.h +++ b/src/platform/Tizen/WiFiManager.h @@ -46,6 +46,7 @@ class WiFiManager CHIP_ERROR Connect(const char * ssid, const char * key, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * apCallback = nullptr); CHIP_ERROR Disconnect(const char * ssid); + CHIP_ERROR StartWiFiScan(ByteSpan ssid, NetworkCommissioning::WiFiDriver::ScanCallback * callback); CHIP_ERROR RemoveAllConfigs(); CHIP_ERROR GetDeviceMACAddress(uint8_t * macAddress, size_t macAddressLen); @@ -55,6 +56,8 @@ class WiFiManager CHIP_ERROR GetConnectionState(wifi_manager_connection_state_e * connectionState); CHIP_ERROR GetBssId(uint8_t * bssId); CHIP_ERROR GetSecurityType(wifi_manager_security_type_e * securityType); + CHIP_ERROR GetConfiguredNetwork(NetworkCommissioning::Network & network); + bool IsWiFiStationConnected(); private: static void _DeviceStateChangedCb(wifi_manager_device_state_e deviceState, void * userData); @@ -66,7 +69,9 @@ class WiFiManager static void _IPConflictCb(char * mac, wifi_manager_ip_conflict_state_e ipConflictState, void * userData); static void _ActivateCb(wifi_manager_error_e wifiErr, void * userData); static void _DeactivateCb(wifi_manager_error_e wifiErr, void * userData); + static void _ScanToConnectFinishedCb(wifi_manager_error_e wifiErr, void * userData); static void _ScanFinishedCb(wifi_manager_error_e wifiErr, void * userData); + static bool _FoundAPOnScanCb(wifi_manager_ap_h ap, void * userData); static bool _FoundAPCb(wifi_manager_ap_h ap, void * userData); static void _ConnectedCb(wifi_manager_error_e wifiErr, void * userData); static bool _ConfigListCb(const wifi_manager_config_h config, void * userData); @@ -75,6 +80,7 @@ class WiFiManager static CHIP_ERROR _WiFiActivate(gpointer userData); static CHIP_ERROR _WiFiDeactivate(gpointer userData); static CHIP_ERROR _WiFiScan(gpointer userData); + static CHIP_ERROR _WiFiScanToConnect(gpointer userData); static CHIP_ERROR _WiFiConnect(wifi_manager_ap_h ap); void _WiFiDeinitialize(); @@ -99,8 +105,10 @@ class WiFiManager uint8_t mWiFiBSSID[kWiFiBSSIDLength]; char mWiFiSSID[kMaxWiFiSSIDLength + 1]; char mWiFiKey[kMaxWiFiKeyLength + 1]; + char mInterestedSSID[kMaxWiFiSSIDLength + 1]; NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * mpConnectCallback; + NetworkCommissioning::WiFiDriver::ScanCallback * mpScanCallback; }; inline WiFiManager & WiFiMgr()