Skip to content

Commit a0588e6

Browse files
[Silabs] Refactor WiFi scanning logic to avoid double async operation in scan API (project-chip#41683)
* Refactor WiFi scanning logic to streamline event handling and improve code clarity * Apply suggestion from @Copilot Co-authored-by: Copilot <[email protected]> * Return error in case of failure. * Fix typo in comment regarding ChipDie initialization in StartNetworkScan function * Remove unused kScan event from WiFi interface event enumeration * Fix semaphore initialization error handling in WifiInterfaceImpl * Refactor WiFi scan handling to improve SSID management and error logging * Clarify comments in StartNetworkScan regarding scan API usage and timeout handling * Refactor WiFi interface includes for improved modularity and clarity * Refactor WiFiInterfaceImpl for improved modularity and clarity * Improve error handling in WiFi scan operations for memory sufficiency * Refactor variable names for clarity in WifiInterfaceImpl.cpp * Use Mutex instead of Semaphore --------- Co-authored-by: Copilot <[email protected]>
1 parent bc70659 commit a0588e6

File tree

3 files changed

+91
-95
lines changed

3 files changed

+91
-95
lines changed

src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp

Lines changed: 91 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ constexpr uint32_t kTimeToFullBeaconReception = 5000; // 5 seconds
107107
wfx_wifi_scan_ext_t temp_reset;
108108

109109
osSemaphoreId_t sScanCompleteSemaphore;
110-
osSemaphoreId_t sScanInProgressSemaphore;
110+
osMutexId_t sScanInProgressSemaphore;
111111

112112
osMessageQueueId_t sWifiEventQueue = nullptr;
113113

@@ -212,9 +212,16 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t
212212
VerifyOrReturnError(result != nullptr, SL_STATUS_NULL_POINTER);
213213
VerifyOrReturnError(wfx_rsi.scan_cb != nullptr, SL_STATUS_INVALID_HANDLE);
214214

215-
uint32_t nbreResults = result->scan_count;
216-
chip::ByteSpan requestedSsidSpan(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length);
215+
sl_wifi_ssid_t * requestedSsidPtr = nullptr;
216+
chip::ByteSpan requestedSsidSpan;
217+
// arg is the requested SSID pointer passed during sl_wifi_set_scan_callback
218+
if (arg != nullptr)
219+
{
220+
requestedSsidPtr = reinterpret_cast<sl_wifi_ssid_t *>(arg);
221+
requestedSsidSpan = chip::ByteSpan(requestedSsidPtr->value, requestedSsidPtr->length);
222+
}
217223

224+
uint32_t nbreResults = result->scan_count;
218225
for (uint32_t i = 0; i < nbreResults; i++)
219226
{
220227
wfx_wifi_scan_result_t currentScanResult = { 0 };
@@ -225,12 +232,14 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t
225232

226233
// Copy the scanned SSID to the current scan ssid buffer that will be forwarded to the callback
227234
chip::MutableByteSpan currentScanSsid(currentScanResult.ssid, WFX_MAX_SSID_LENGTH);
228-
chip::CopySpanToMutableSpan(scannedSsidSpan, currentScanSsid);
235+
VerifyOrReturnError(chip::CopySpanToMutableSpan(scannedSsidSpan, currentScanSsid) == CHIP_NO_ERROR,
236+
SL_STATUS_SI91X_MEMORY_IS_NOT_SUFFICIENT);
229237
currentScanResult.ssid_length = currentScanSsid.size();
230238

231239
chip::ByteSpan inBssid(result->scan_info[i].bssid, kWifiMacAddressLength);
232240
chip::MutableByteSpan outBssid(currentScanResult.bssid, kWifiMacAddressLength);
233-
chip::CopySpanToMutableSpan(inBssid, outBssid);
241+
VerifyOrReturnError(chip::CopySpanToMutableSpan(inBssid, outBssid) == CHIP_NO_ERROR,
242+
SL_STATUS_SI91X_MEMORY_IS_NOT_SUFFICIENT);
234243

235244
// TODO: We should revisit this to make sure we are setting the correct values
236245
currentScanResult.security = static_cast<wfx_sec_t>(result->scan_info[i].security_mode);
@@ -240,6 +249,7 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t
240249
currentScanResult.wiFiBand = WiFiBandEnum::k2g4;
241250

242251
// if user has provided ssid, check if the current scan result ssid matches the user provided ssid
252+
// NOTE: background scan does not filter by ssid, so we need to do it here
243253
if (!requestedSsidSpan.empty())
244254
{
245255
if (requestedSsidSpan.data_equal(currentScanSsid))
@@ -253,15 +263,11 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t
253263
}
254264
}
255265

256-
// cleanup and return
257-
wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kScanStarted);
258266
wfx_rsi.scan_cb(nullptr);
267+
// cleanup and return
259268
wfx_rsi.scan_cb = nullptr;
260-
if (wfx_rsi.scan_ssid)
261-
{
262-
chip::Platform::MemoryFree(wfx_rsi.scan_ssid);
263-
wfx_rsi.scan_ssid = nullptr;
264-
}
269+
270+
wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kScanStarted);
265271
osSemaphoreRelease(sScanCompleteSemaphore);
266272

267273
return SL_STATUS_OK;
@@ -373,7 +379,7 @@ sl_status_t InitiateScan()
373379

374380
sl_wifi_set_scan_callback(ScanCallback, NULL);
375381

376-
osSemaphoreAcquire(sScanInProgressSemaphore, osWaitForever);
382+
osMutexAcquire(sScanInProgressSemaphore, osWaitForever);
377383

378384
// This is an odd success code?
379385
status = sl_wifi_start_scan(SL_WIFI_CLIENT_2_4GHZ_INTERFACE, &ssid, &wifi_scan_configuration);
@@ -383,7 +389,7 @@ sl_status_t InitiateScan()
383389
status = SL_STATUS_OK;
384390
}
385391

386-
osSemaphoreRelease(sScanInProgressSemaphore);
392+
osMutexRelease(sScanInProgressSemaphore);
387393
VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogProgress(DeviceLayer, "sl_wifi_start_scan failed: 0x%lx", status));
388394

389395
return status;
@@ -565,8 +571,8 @@ CHIP_ERROR WifiInterfaceImpl::InitWiFiStack(void)
565571
VerifyOrReturnError(sScanCompleteSemaphore != nullptr, CHIP_ERROR_NO_MEMORY);
566572

567573
// Create Semaphore for scan in-progress protection
568-
sScanInProgressSemaphore = osSemaphoreNew(1, 1, nullptr);
569-
VerifyOrReturnError(sScanCompleteSemaphore != nullptr, CHIP_ERROR_NO_MEMORY);
574+
sScanInProgressSemaphore = osMutexNew(nullptr);
575+
VerifyOrReturnError(sScanInProgressSemaphore != nullptr, CHIP_ERROR_NO_MEMORY);
570576

571577
// Create the message queue
572578
sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiPlatformEvent), nullptr);
@@ -611,69 +617,6 @@ void WifiInterfaceImpl::ProcessEvent(WifiPlatformEvent event)
611617
// TODO: Currently unimplemented
612618
break;
613619

614-
case WifiPlatformEvent::kScan:
615-
ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan");
616-
if (!(wfx_rsi.dev_state.Has(WifiInterface::WifiState::kScanStarted)))
617-
{
618-
ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan");
619-
sl_status_t status = SL_STATUS_OK;
620-
621-
sl_wifi_scan_configuration_t wifi_scan_configuration = default_wifi_scan_configuration;
622-
if (wfx_rsi.dev_state.Has(WifiInterface::WifiState::kStationConnected))
623-
{
624-
/* Terminate with end of scan which is no ap sent back */
625-
wifi_scan_configuration.type = SL_WIFI_SCAN_TYPE_ADV_SCAN;
626-
wifi_scan_configuration.periodic_scan_interval = kAdvScanPeriodicity;
627-
}
628-
629-
sl_wifi_advanced_scan_configuration_t advanced_scan_configuration = {
630-
.trigger_level = kAdvScanThreshold,
631-
.trigger_level_change = kAdvRssiToleranceThreshold,
632-
.active_channel_time = kAdvActiveScanDuration,
633-
.passive_channel_time = kAdvPassiveScanDuration,
634-
.enable_instant_scan = kAdvEnableInstantbgScan,
635-
.enable_multi_probe = kAdvMultiProbe,
636-
};
637-
638-
status = sl_wifi_set_advanced_scan_configuration(&advanced_scan_configuration);
639-
640-
// TODO: Seems like Chipdie should be called here, the device should be initialized here
641-
VerifyOrReturn(
642-
status == SL_STATUS_OK,
643-
ChipLogError(DeviceLayer, "sl_wifi_set_advanced_scan_configuration failed: 0x%lx", static_cast<uint32_t>(status)));
644-
645-
sl_wifi_set_scan_callback(BackgroundScanCallback, nullptr);
646-
wfx_rsi.dev_state.Set(WifiInterface::WifiState::kScanStarted);
647-
648-
// If an ssid was not provided, we need to call the scan API with nullptr to scan all Wi-Fi networks
649-
sl_wifi_ssid_t ssid = { 0 };
650-
sl_wifi_ssid_t * ssidPtr = nullptr;
651-
652-
if (wfx_rsi.scan_ssid != nullptr)
653-
{
654-
chip::ByteSpan requestedSsid(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length);
655-
chip::MutableByteSpan ouputSsid(ssid.value, sizeof(ssid.value));
656-
chip::CopySpanToMutableSpan(requestedSsid, ouputSsid);
657-
658-
ssid.length = ouputSsid.size();
659-
ssidPtr = &ssid;
660-
}
661-
662-
osSemaphoreAcquire(sScanInProgressSemaphore, osWaitForever);
663-
status = sl_wifi_start_scan(SL_WIFI_CLIENT_2_4GHZ_INTERFACE, ssidPtr, &wifi_scan_configuration);
664-
if (SL_STATUS_IN_PROGRESS == status)
665-
{
666-
osSemaphoreAcquire(sScanCompleteSemaphore, kWifiScanTimeoutTicks);
667-
}
668-
669-
osSemaphoreRelease(sScanInProgressSemaphore);
670-
if (status != SL_STATUS_OK)
671-
{
672-
ChipLogError(DeviceLayer, "sl_wifi_start_scan failed: 0x%lx", status);
673-
}
674-
}
675-
break;
676-
677620
case WifiPlatformEvent::kStationStartJoin:
678621
ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationStartJoin");
679622

@@ -922,26 +865,82 @@ CHIP_ERROR WifiInterfaceImpl::StartNetworkScan(chip::ByteSpan ssid, ::ScanCallba
922865
// SSID Max Length that is supported by the Wi-Fi SDK is 32
923866
VerifyOrReturnError(ssid.size() <= WFX_MAX_SSID_LENGTH, CHIP_ERROR_INVALID_STRING_LENGTH);
924867

925-
if (ssid.empty()) // Scan all networks
868+
wfx_rsi.dev_state.Set(WifiInterface::WifiState::kScanStarted);
869+
wfx_rsi.scan_cb = callback;
870+
871+
sl_status_t status = SL_STATUS_OK;
872+
873+
sl_wifi_scan_configuration_t wifi_scan_configuration = default_wifi_scan_configuration;
874+
if (wfx_rsi.dev_state.Has(WifiInterface::WifiState::kStationConnected))
926875
{
927-
wfx_rsi.scan_ssid_length = 0;
928-
wfx_rsi.scan_ssid = nullptr;
876+
/* Terminate with end of scan which is no ap sent back */
877+
wifi_scan_configuration.type = SL_WIFI_SCAN_TYPE_ADV_SCAN;
878+
wifi_scan_configuration.periodic_scan_interval = kAdvScanPeriodicity;
929879
}
930-
else // Scan specific SSID
880+
881+
sl_wifi_advanced_scan_configuration_t advanced_scan_configuration = {
882+
.trigger_level = kAdvScanThreshold,
883+
.trigger_level_change = kAdvRssiToleranceThreshold,
884+
.active_channel_time = kAdvActiveScanDuration,
885+
.passive_channel_time = kAdvPassiveScanDuration,
886+
.enable_instant_scan = kAdvEnableInstantbgScan,
887+
.enable_multi_probe = kAdvMultiProbe,
888+
};
889+
890+
status = sl_wifi_set_advanced_scan_configuration(&advanced_scan_configuration);
891+
892+
if (status != SL_STATUS_OK)
931893
{
932-
wfx_rsi.scan_ssid_length = ssid.size();
933-
wfx_rsi.scan_ssid = reinterpret_cast<uint8_t *>(chip::Platform::MemoryAlloc(wfx_rsi.scan_ssid_length));
934-
VerifyOrReturnError(wfx_rsi.scan_ssid != nullptr, CHIP_ERROR_NO_MEMORY);
894+
// Since the log is required for debugging and the error log is present in the invoker itself
895+
ChipLogDetail(DeviceLayer, "sl_wifi_set_advanced_scan_configuration failed: 0x%lx", static_cast<uint32_t>(status));
896+
897+
// Reset the scan state in case of failure
898+
wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kScanStarted);
899+
wfx_rsi.scan_cb = nullptr;
935900

936-
chip::MutableByteSpan scanSsidSpan(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length);
937-
chip::CopySpanToMutableSpan(ssid, scanSsidSpan);
901+
return CHIP_ERROR_INTERNAL;
938902
}
939-
wfx_rsi.scan_cb = callback;
940903

941-
// TODO: We should be calling the start function directly instead of doing it asynchronously
942-
WifiPlatformEvent event = WifiPlatformEvent::kScan;
943-
PostWifiPlatformEvent(event);
904+
// If an ssid was not provided, we need to call sl_wifi_start_scan with nullptr to scan all Wi-Fi networks
905+
sl_wifi_ssid_t requestedSsid = { 0 };
906+
sl_wifi_ssid_t * requestedSsidPtr = nullptr;
907+
908+
if (!ssid.empty())
909+
{
910+
// Copy the requested SSID to the sl_wifi_ssid_t structure
911+
chip::MutableByteSpan requestedSsidSpan(requestedSsid.value, sizeof(requestedSsid.value));
912+
ReturnErrorOnFailure(chip::CopySpanToMutableSpan(ssid, requestedSsidSpan));
913+
// Copy the length of the requested SSID to the sl_wifi_ssid_t structure
914+
requestedSsid.length = static_cast<uint8_t>(ssid.size());
915+
requestedSsidPtr = &requestedSsid;
916+
}
944917

918+
osMutexAcquire(sScanInProgressSemaphore, osWaitForever);
919+
920+
// NOTE: sending requestedSsidPtr as background scan does not filter for SSID
921+
sl_wifi_set_scan_callback(BackgroundScanCallback, requestedSsidPtr);
922+
status = sl_wifi_start_scan(SL_WIFI_CLIENT_2_4GHZ_INTERFACE, requestedSsidPtr, &wifi_scan_configuration);
923+
924+
if (SL_STATUS_IN_PROGRESS == status)
925+
{
926+
// NOTE: Intentional to wait for timeout here as the scan completion is indicated by the callback
927+
osSemaphoreAcquire(sScanCompleteSemaphore, kWifiScanTimeoutTicks);
928+
}
929+
930+
osMutexRelease(sScanInProgressSemaphore);
931+
932+
// Check for errors other than in-progress, since the sl_wifi_start_scan can return in-progress as a success code
933+
if (status != SL_STATUS_OK && status != SL_STATUS_IN_PROGRESS)
934+
{
935+
// Since the log is required for debugging and the error log is present in the invoker itself
936+
ChipLogDetail(DeviceLayer, "sl_wifi_start_scan failed: 0x%04lx", static_cast<uint32_t>(status));
937+
938+
// Reset the scan state in case of failure
939+
wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kScanStarted);
940+
wfx_rsi.scan_cb = nullptr;
941+
942+
return CHIP_ERROR_INTERNAL;
943+
}
945944
return CHIP_NO_ERROR;
946945
}
947946

src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class WifiInterfaceImpl final : public WifiInterface
3434
kStationDisconnect = 1,
3535
kAPStart = 2,
3636
kAPStop = 3,
37-
kScan = 4, /* This combines the scan start and scan result events */
3837
kStationStartJoin = 5,
3938
kConnectionComplete = 6, /* This combines the DHCP and Notify */
4039
kStationDhcpDone = 7,

src/platform/silabs/wifi/WifiInterface.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,6 @@ typedef struct wfx_rsi_s
438438
uint16_t ap_chan; /* The chan our STA is using */
439439
chip::DeviceLayer::Silabs::WifiInterface::WifiCredentials credentials;
440440
ScanCallback scan_cb;
441-
uint8_t * scan_ssid; /* Which one are we scanning for */
442-
size_t scan_ssid_length;
443441
#ifdef SL_WFX_CONFIG_SOFTAP
444442
chip::DeviceLayer::Silabs::WifiInterface::MacAddress softap_mac;
445443
#endif

0 commit comments

Comments
 (0)