[wlan][policy] Handle canceled scans

This CL handles canceled scans (code CANCELED_BY_DRIVER_OR_FIRMWARE)
in a similar way to scans that are rejected (code SHOULD_WAIT). Both
of these cases happen when a SoftAP startup or connection attempt cause
scanning to be unavailable, and should have a similar reaction at the
Policy layer.

Bug: 73633
Test: fx test wlancfg-tests wlanstack-tests
Change-Id: I78b0e9770815f37c3a257673bddcde1c98e48fab
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/510638
Commit-Queue: Marc Khouri <mnck@google.com>
Fuchsia-Auto-Submit: Marc Khouri <mnck@google.com>
Reviewed-by: Kevin Sakuma <sakuma@google.com>
Reviewed-by: Rebecca Silberstein <silberst@google.com>
API-Review: Rebecca Silberstein <silberst@google.com>
diff --git a/sdk/fidl/fuchsia.wlan.sme/sme.fidl b/sdk/fidl/fuchsia.wlan.sme/sme.fidl
index df97fd4c..4f84c38 100644
--- a/sdk/fidl/fuchsia.wlan.sme/sme.fidl
+++ b/sdk/fidl/fuchsia.wlan.sme/sme.fidl
@@ -59,6 +59,7 @@
     NOT_SUPPORTED = 1;
     INTERNAL_ERROR = 2;
     SHOULD_WAIT = 3;
+    CANCELED_BY_DRIVER_OR_FIRMWARE = 4;
 };
 
 struct ScanError {
diff --git a/src/connectivity/wlan/wlancfg/src/client/scan.rs b/src/connectivity/wlan/wlancfg/src/client/scan.rs
index 77d39bb..f5aec85 100644
--- a/src/connectivity/wlan/wlancfg/src/client/scan.rs
+++ b/src/connectivity/wlan/wlancfg/src/client/scan.rs
@@ -83,11 +83,15 @@
                 }
                 fidl_sme::ScanTransactionEvent::OnError { error } => {
                     error!("Scan error from SME: {:?}", error);
-                    return Err(if error.code == fidl_sme::ScanErrorCode::ShouldWait {
-                        SmeScanError::ShouldRetryLater
-                    } else {
-                        SmeScanError::Other
-                    });
+                    return Err(
+                        if error.code == fidl_sme::ScanErrorCode::ShouldWait
+                            || error.code == fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware
+                        {
+                            SmeScanError::ShouldRetryLater
+                        } else {
+                            SmeScanError::Other
+                        },
+                    );
                 }
             };
         }
@@ -1129,6 +1133,7 @@
 
     #[test_case(fidl_sme::ScanErrorCode::ShouldWait, false; "SME scan error ShouldWait with failed retry")]
     #[test_case(fidl_sme::ScanErrorCode::ShouldWait, true; "SME scan error ShouldWait with successful retry")]
+    #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, true; "SME scan error CanceledByDriverOrFirmware with successful retry")]
     fn sme_scan_error_with_retry(error_code: fidl_sme::ScanErrorCode, retry_succeeds: bool) {
         let mut exec = fasync::Executor::new().expect("failed to create an executor");
         let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
diff --git a/src/connectivity/wlan/wlanstack/src/station/client.rs b/src/connectivity/wlan/wlanstack/src/station/client.rs
index c2f00ac..1a7599e 100644
--- a/src/connectivity/wlan/wlanstack/src/station/client.rs
+++ b/src/connectivity/wlan/wlanstack/src/station/client.rs
@@ -259,6 +259,10 @@
                     code: fidl_sme::ScanErrorCode::ShouldWait,
                     message: "Scanning is temporarily unavailable".to_string(),
                 },
+                fidl_mlme::ScanResultCode::CanceledByDriverOrFirmware => fidl_sme::ScanError {
+                    code: fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware,
+                    message: "Scanning was canceled by driver or FW".to_string(),
+                },
                 _ => fidl_sme::ScanError {
                     code: fidl_sme::ScanErrorCode::InternalError,
                     message: "Internal error occurred".to_string(),
@@ -351,6 +355,11 @@
         "Scanning not supported by device"
     )]
     #[test_case(
+        fidl_mlme::ScanResultCode::CanceledByDriverOrFirmware,
+        fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware,
+        "Scanning was canceled by driver or FW"
+    )]
+    #[test_case(
         fidl_mlme::ScanResultCode::InvalidArgs,
         fidl_sme::ScanErrorCode::InternalError,
         "Internal error occurred"