Make WiFi HAL compatible with VTS

The initial WiFi HAL implementation had enough functionality to make the
Android framework happy. It did not pass VTS however. This change fixes
that by implementing all functions required by VTS. It also resolves
some threading issues where VTS relies on cleanup being a synchronous
operation despite having a callback to indicate when the cleanup
completes.

Bug: 69479497
Test: run vts -m VtsHalWifiV1_0Target
Change-Id: Ifc75139e7ff8b3a7d51f633e671e613ed56868d4
(cherry picked from commit 6efb6651e863629f373a45a4f4261c417c13b6da)
(cherry picked from commit 51356944e1b7dac2b8c16bd86f2d8d07163c47c7)
diff --git a/wifi/wifi_hal/Android.mk b/wifi/wifi_hal/Android.mk
index ff571bc..17d0ab4 100644
--- a/wifi/wifi_hal/Android.mk
+++ b/wifi/wifi_hal/Android.mk
@@ -25,6 +25,7 @@
 
 
 LOCAL_SRC_FILES := \
+	halstate.cpp \
 	info.cpp \
 	interface.cpp \
 	netlink.cpp \
diff --git a/wifi/wifi_hal/halstate.cpp b/wifi/wifi_hal/halstate.cpp
new file mode 100644
index 0000000..0dcdf9d
--- /dev/null
+++ b/wifi/wifi_hal/halstate.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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 "halstate.h"
+
+HalState::HalState() : mState(State::Constructed) {
+}
+
+bool HalState::init() {
+    // Ensure that checking the state and waiting on the condition is atomic.
+    std::unique_lock<std::mutex> lock(mStateMutex);
+
+    if (mState != State::Stopped && mState != State::Constructed) {
+        // We can only initialize when freshly constructed or stopped
+        return false;
+    }
+    if (mInfo) {
+        // We are in the correct state but our info object is still allocated.
+        // This is a logic error somewhere and should not happen.
+        return false;
+    }
+    auto info = std::make_unique<Info>();
+    if (info->init()) {
+        // Only store the info object to keep it alive if init succeeded.
+        // Otherwise we're going to remain in the previous state and having an
+        // uninitialized info object around will cause inconsistency.
+        mInfo = std::move(info);
+        mState = State::Initialized;
+        return true;
+    }
+    // If we failed to initalize we remain in the same state.
+    return false;
+}
+
+bool HalState::stop(StopHandler stopHandler) {
+    {
+        // Ensure atomicity in checking and setting state
+        std::unique_lock<std::mutex> lock(mStateMutex);
+
+        if (mState == State::Stopping || mState == State::Stopped) {
+            // Already stopping or stopped, nothing to do
+            return false;
+        }
+        if (mState != State::Running) {
+            // Make sure there is no info object anymore. It should never exist
+            // in the stopped state.
+            mInfo.reset();
+            // If we're neither stopping, stopped nor running then we can't stop
+            // again. It seems that sometimes the client expects to be able to
+            // call this when initialized or constructed so we'll set the state
+            // to stopped. We have to return false to prevent the caller from
+            // waiting for the callback though. Calling the callback here from
+            // the same thread that called stop could cause a deadlock.
+            mState = State::Stopped;
+            return false;
+        }
+        mState = State::Stopping;
+    }
+    mInfo->stop(std::bind(&HalState::onStop, this, stopHandler));
+    // We have now requested the stop, we'll change state in the stop handler
+    // when it's called.
+    return true;
+}
+
+bool HalState::eventLoop() {
+    {
+        // Atomically check and set state to running
+        std::unique_lock<std::mutex> lock(mStateMutex);
+        if (mState != State::Initialized || !mInfo) {
+            return false;
+        }
+        mState = State::Running;
+    }
+    mInfo->eventLoop();
+    return true;
+}
+
+Info* HalState::info() {
+    return mInfo.get();
+}
+
+void HalState::onStop(StopHandler stopHandler) {
+    stopHandler();
+    mInfo.reset();
+
+    std::unique_lock<std::mutex> lock(mStateMutex);
+    mState = State::Stopped;
+}
+
diff --git a/wifi/wifi_hal/halstate.h b/wifi/wifi_hal/halstate.h
new file mode 100644
index 0000000..1c63886
--- /dev/null
+++ b/wifi/wifi_hal/halstate.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "info.h"
+
+#include <memory>
+#include <mutex>
+
+// A class that keeps track of the current state of the WiFi HAL. This is
+// accomplished by having the HAL call this state tracker which in turn will
+// call the appropriate functionality.
+//
+// This is needed because the HAL must have some form of global state to prevent
+// situations where the HAL is initialized while stopping. This class allows
+// the Info class to stay relatively simple and this class can focus on just the
+// state behavior.
+class HalState {
+public:
+    using StopHandler = std::function<void ()>;
+
+    HalState();
+
+    bool init();
+    bool stop(StopHandler stopHandler);
+    bool eventLoop();
+
+    Info* info();
+
+private:
+    enum class State {
+        Constructed,
+        Initialized,
+        Running,
+        Stopping,
+        Stopped,
+    };
+
+    void onStop(StopHandler stopHandler);
+
+    std::unique_ptr<Info> mInfo;
+    std::mutex mStateMutex;
+    State mState;
+};
+
diff --git a/wifi/wifi_hal/interface.cpp b/wifi/wifi_hal/interface.cpp
index 141540f..f3d1f13 100644
--- a/wifi/wifi_hal/interface.cpp
+++ b/wifi/wifi_hal/interface.cpp
@@ -26,6 +26,29 @@
 static const char kFirmwareVersion[] = "1.0";
 static const char kDriverVersion[] = "1.0";
 
+// A list of supported channels in the 2.4 GHz band, values in MHz
+static const wifi_channel k2p4Channels[] = {
+    2412,
+    2417,
+    2422,
+    2427,
+    2432,
+    2437,
+    2442,
+    2447,
+    2452,
+    2457,
+    2462,
+    2467,
+    2472,
+    2484
+};
+
+template<typename T, size_t N>
+constexpr size_t arraySize(const T (&)[N]) {
+    return N;
+}
+
 Interface::Interface(Netlink& netlink, const char* name)
     : mNetlink(netlink)
     , mName(name)
@@ -112,6 +135,128 @@
     return WIFI_SUCCESS;
 }
 
+wifi_error Interface::setScanningMacOui(oui /*scan_oui*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::clearLinkStats(u32 /*requestMask*/,
+                                     u32* responseMask,
+                                     u8 /*request*/,
+                                     u8* response) {
+    if (responseMask == nullptr || response == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getValidChannels(int band,
+                                       int maxChannels,
+                                       wifi_channel* channels,
+                                       int* numChannels) {
+    if (channels == nullptr || numChannels == nullptr || maxChannels < 0) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    switch (band) {
+        case WIFI_BAND_BG: // 2.4 GHz
+            *numChannels = std::min<int>(maxChannels,
+                                         arraySize(k2p4Channels));
+            memcpy(channels, k2p4Channels, *numChannels);
+
+            return WIFI_SUCCESS;
+        default:
+            return WIFI_ERROR_NOT_SUPPORTED;
+    }
+}
+
+wifi_error Interface::startLogging(u32 /*verboseLevel*/,
+                                   u32 /*flags*/,
+                                   u32 /*maxIntervalSec*/,
+                                   u32 /*minDataSize*/,
+                                   char* /*ringName*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::setCountryCode(const char* /*countryCode*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::setLogHandler(wifi_request_id /*id*/,
+                                    wifi_ring_buffer_data_handler /*handler*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getRingBuffersStatus(u32* numRings,
+                                           wifi_ring_buffer_status* status) {
+    if (numRings == nullptr || status == nullptr || *numRings == 0) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    memset(status, 0, sizeof(*status));
+    strlcpy(reinterpret_cast<char*>(status->name),
+            "ring0",
+            sizeof(status->name));
+    *numRings = 1;
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getLoggerSupportedFeatureSet(unsigned int* support) {
+    if (support == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    *support = 0;
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getRingData(char* /*ringName*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::configureNdOffload(u8 /*enable*/) {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::startPacketFateMonitoring() {
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getTxPacketFates(wifi_tx_report* /*txReportBuffers*/,
+                                       size_t /*numRequestedFates*/,
+                                       size_t* numProvidedFates) {
+    if (numProvidedFates == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    *numProvidedFates = 0;
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getRxPacketFates(wifi_rx_report* /*rxReportBuffers*/,
+                                       size_t /*numRequestedFates*/,
+                                       size_t* numProvidedFates) {
+    if (numProvidedFates == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    *numProvidedFates = 0;
+    return WIFI_SUCCESS;
+}
+
+wifi_error Interface::getPacketFilterCapabilities(u32* version,
+                                                  u32* maxLength) {
+    if (version == nullptr || maxLength == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    *version = 0;
+    *maxLength = 0;
+    return WIFI_SUCCESS;
+}
+
+wifi_error
+Interface::getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount) {
+    if (wakeReasonCount == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    return WIFI_SUCCESS;
+}
+
 void Interface::onLinkStatsReply(wifi_request_id requestId,
                                  wifi_stats_result_handler handler,
                                  const NetlinkMessage& message) {
diff --git a/wifi/wifi_hal/interface.h b/wifi/wifi_hal/interface.h
index 1955a9a..fb7e6ce 100644
--- a/wifi/wifi_hal/interface.h
+++ b/wifi/wifi_hal/interface.h
@@ -40,6 +40,37 @@
     wifi_error resetAlertHandler(wifi_request_id id);
     wifi_error getFirmwareVersion(char* buffer, size_t size);
     wifi_error getDriverVersion(char* buffer, size_t size);
+    wifi_error setScanningMacOui(oui scan_oui);
+    wifi_error clearLinkStats(u32 requestMask,
+                              u32* responseMask,
+                              u8 request,
+                              u8* response);
+    wifi_error getValidChannels(int band,
+                                int maxChannels,
+                                wifi_channel* channels,
+                                int* numChannels);
+    wifi_error startLogging(u32 verboseLevel,
+                            u32 flags,
+                            u32 maxIntervalSec,
+                            u32 minDataSize,
+                            char* ringName);
+    wifi_error setCountryCode(const char* countryCode);
+    wifi_error setLogHandler(wifi_request_id id,
+                             wifi_ring_buffer_data_handler handler);
+    wifi_error getRingBuffersStatus(u32* numRings,
+                                    wifi_ring_buffer_status* status);
+    wifi_error getLoggerSupportedFeatureSet(unsigned int* support);
+    wifi_error getRingData(char* ringName);
+    wifi_error configureNdOffload(u8 enable);
+    wifi_error startPacketFateMonitoring();
+    wifi_error getTxPacketFates(wifi_tx_report* txReportBuffers,
+                                size_t numRequestedFates,
+                                size_t* numProvidedFates);
+    wifi_error getRxPacketFates(wifi_rx_report* rxReportBuffers,
+                                size_t numRequestedFates,
+                                size_t* numProvidedFates);
+    wifi_error getPacketFilterCapabilities(u32* version, u32* maxLength);
+    wifi_error getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount);
 private:
     Interface(const Interface&) = delete;
     Interface& operator=(const Interface&) = delete;
diff --git a/wifi/wifi_hal/netlink.cpp b/wifi/wifi_hal/netlink.cpp
index f82d3da..b462f2a 100644
--- a/wifi/wifi_hal/netlink.cpp
+++ b/wifi/wifi_hal/netlink.cpp
@@ -122,7 +122,6 @@
                 readNetlinkMessage(fd.fd);
             } else if (fd.fd == mControlPipe[kControlRead]) {
                 if (readControlMessage()) {
-                    ALOGE("Received request to stop event loop, quitting");
                     // Make a copy of the stop handler while holding the lock
                     // and then call it after releasing the lock. This prevents
                     // the potential deadlock of someone calling stop from the
diff --git a/wifi/wifi_hal/wifi_hal.cpp b/wifi/wifi_hal/wifi_hal.cpp
index d526565..3178d1b 100644
--- a/wifi/wifi_hal/wifi_hal.cpp
+++ b/wifi/wifi_hal/wifi_hal.cpp
@@ -16,6 +16,7 @@
 
 #include <wifi_hal.h>
 
+#include "halstate.h"
 #include "info.h"
 #include "interface.h"
 
@@ -39,8 +40,12 @@
     val = &NotSupportedFunction<T>::invoke;
 }
 
+HalState* asHalState(wifi_handle h) {
+    return reinterpret_cast<HalState*>(h);
+}
+
 Info* asInfo(wifi_handle h) {
-    return reinterpret_cast<Info*>(h);
+    return asHalState(h)->info();
 }
 
 Interface* asInterface(wifi_interface_handle h) {
@@ -52,13 +57,22 @@
         return WIFI_ERROR_INVALID_ARGS;
     }
 
-    // Do this using a unique_ptr to ensure someone is always owning and
-    // destroying the pointer.
-    auto info = std::make_unique<Info>();
-    if (!info->init()) {
+    // Make the HAL state static inside the function for lazy construction. When
+    // stopping we want to keep track of the current HAL state because if the
+    // HAL starts again we need to know if we're in a state where we can start
+    // or not. If we're stopping with the intention of never starting back up
+    // again we could destroy the HAL state. Unfortunately there is no
+    // distinction between these two events so the safe choice is to leak this
+    // memory and always keep track of the HAL state. This is allocated on the
+    // heap instead of the stack to prevent any destructors being called when
+    // the dynamic library is being unloaded since the program state could be
+    // unreliable at this point.
+    static HalState* sHalState = new HalState();
+
+    if (!sHalState->init()) {
         return WIFI_ERROR_UNKNOWN;
     }
-    *handle = reinterpret_cast<wifi_handle>(info.release());
+    *handle = reinterpret_cast<wifi_handle>(sHalState);
 
     return WIFI_SUCCESS;
 }
@@ -68,10 +82,32 @@
         return;
     }
 
-    auto info = asInfo(handle);
-    // When the stop completes it will call this lambda which in turn notifies
-    // the provided handler and then cleans up the object.
-    info->stop([=] { handler(handle); delete info; });
+    std::condition_variable condition;
+    std::mutex mutex;
+    std::unique_lock<std::mutex> lock(mutex);
+    bool stopped = false;
+    // This lambda will be called when the stop completes. That will notify the
+    // condition variable and this function will wake up and exit. This ensures
+    // that this function is synchronous. The boolean is to ensure that when
+    // waiting we're protected against spurious wakeups, we only exit once the
+    // callback has signaled that it's been called.
+    auto callback = [&mutex, &stopped, &condition] {
+        std::unique_lock<std::mutex> lock(mutex);
+        stopped = true;
+        condition.notify_all();
+    };
+    if (asHalState(handle)->stop(callback)) {
+        // The handler succeeded and will call our callback, wait for it. If the
+        // stop call did not succeed we can't wait for this condition since our
+        // callback will never call notify on it.
+        while (!stopped) {
+            condition.wait(lock);
+        }
+    }
+    // The HAL seems to expect this callback to happen on the same thread, or at
+    // least that's what happens in other WiFi HALs. This is why this method has
+    // to be synchronous.
+    handler(handle);
 }
 
 void wifi_event_loop(wifi_handle handle) {
@@ -79,7 +115,7 @@
         return;
     }
 
-    asInfo(handle)->eventLoop();
+    asHalState(handle)->eventLoop();
 }
 
 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle,
@@ -169,6 +205,171 @@
     return asInterface(handle)->getDriverVersion(buffer, buffer_size);
 }
 
+wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle,
+                                     oui scan_oui) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->setScanningMacOui(scan_oui);
+}
+
+wifi_error wifi_clear_link_stats(wifi_interface_handle handle,
+                                 u32 stats_clear_req_mask,
+                                 u32 *stats_clear_rsp_mask,
+                                 u8 stop_req,
+                                 u8 *stop_rsp) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->clearLinkStats(stats_clear_req_mask,
+                                               stats_clear_rsp_mask,
+                                               stop_req,
+                                               stop_rsp);
+}
+
+wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
+                                   int band,
+                                   int max_channels,
+                                   wifi_channel *channels,
+                                   int *num_channels)
+{
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getValidChannels(band,
+                                                 max_channels,
+                                                 channels,
+                                                 num_channels);
+}
+
+wifi_error wifi_start_logging(wifi_interface_handle handle,
+                              u32 verbose_level,
+                              u32 flags,
+                              u32 max_interval_sec,
+                              u32 min_data_size,
+                              char *ring_name) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->startLogging(verbose_level,
+                                             flags,
+                                             max_interval_sec,
+                                             min_data_size,
+                                             ring_name);
+}
+
+wifi_error wifi_set_country_code(wifi_interface_handle handle,
+                                 const char *country_code) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->setCountryCode(country_code);
+}
+
+wifi_error wifi_set_log_handler(wifi_request_id id,
+                                wifi_interface_handle handle,
+                                wifi_ring_buffer_data_handler handler) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->setLogHandler(id, handler);
+}
+
+wifi_error wifi_get_ring_buffers_status(wifi_interface_handle handle,
+                                        u32 *num_rings,
+                                        wifi_ring_buffer_status *status) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getRingBuffersStatus(num_rings, status);
+}
+
+wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle handle,
+                                                 unsigned int *support) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getLoggerSupportedFeatureSet(support);
+}
+
+wifi_error wifi_get_ring_data(wifi_interface_handle handle, char *ring_name) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getRingData(ring_name);
+}
+
+wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->configureNdOffload(enable);
+}
+
+wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->startPacketFateMonitoring();
+}
+
+wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
+                                 wifi_tx_report *tx_report_bufs,
+                                 size_t n_requested_fates,
+                                 size_t *n_provided_fates) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getTxPacketFates(tx_report_bufs,
+                                                 n_requested_fates,
+                                                 n_provided_fates);
+}
+
+wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
+                                 wifi_rx_report *rx_report_bufs,
+                                 size_t n_requested_fates,
+                                 size_t *n_provided_fates) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getRxPacketFates(rx_report_bufs,
+                                                 n_requested_fates,
+                                                 n_provided_fates);
+}
+
+wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
+                                               u32 *version,
+                                               u32 *max_len) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getPacketFilterCapabilities(version, max_len);
+}
+
+wifi_error
+wifi_get_wake_reason_stats(wifi_interface_handle handle,
+                           WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) {
+    if (handle == nullptr) {
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return asInterface(handle)->getWakeReasonStats(wifi_wake_reason_cnt);
+}
+
 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn* fn)
 {
     if (fn == NULL) {
@@ -183,14 +384,31 @@
     fn->wifi_get_iface_name = wifi_get_iface_name;
     fn->wifi_get_link_stats = wifi_get_link_stats;
     fn->wifi_set_link_stats = wifi_set_link_stats;
+    fn->wifi_clear_link_stats = wifi_clear_link_stats;
 
     fn->wifi_set_alert_handler = wifi_set_alert_handler;
     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
     fn->wifi_get_firmware_version = wifi_get_firmware_version;
     fn->wifi_get_driver_version = wifi_get_driver_version;
 
+    fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
+    fn->wifi_get_valid_channels = wifi_get_valid_channels;
+    fn->wifi_start_logging = wifi_start_logging;
+    fn->wifi_set_country_code = wifi_set_country_code;
+    fn->wifi_set_log_handler = wifi_set_log_handler;
+    fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
+    fn->wifi_get_logger_supported_feature_set
+        = wifi_get_logger_supported_feature_set;
+    fn->wifi_get_ring_data = wifi_get_ring_data;
+    fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
+    fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
+    fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
+    fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
+    fn->wifi_get_packet_filter_capabilities
+        = wifi_get_packet_filter_capabilities;
+    fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
+
     // These function will either return WIFI_ERROR_NOT_SUPPORTED or do nothing
-    notSupported(fn->wifi_set_scanning_mac_oui);
     notSupported(fn->wifi_set_nodfs_flag);
     notSupported(fn->wifi_get_concurrency_matrix);
     notSupported(fn->wifi_start_gscan);
@@ -201,33 +419,20 @@
     notSupported(fn->wifi_set_significant_change_handler);
     notSupported(fn->wifi_reset_significant_change_handler);
     notSupported(fn->wifi_get_gscan_capabilities);
-    notSupported(fn->wifi_clear_link_stats);
-    notSupported(fn->wifi_get_valid_channels);
     notSupported(fn->wifi_rtt_range_request);
     notSupported(fn->wifi_rtt_range_cancel);
     notSupported(fn->wifi_get_rtt_capabilities);
     notSupported(fn->wifi_rtt_get_responder_info);
     notSupported(fn->wifi_enable_responder);
     notSupported(fn->wifi_disable_responder);
-    notSupported(fn->wifi_start_logging);
     notSupported(fn->wifi_set_epno_list);
     notSupported(fn->wifi_reset_epno_list);
-    notSupported(fn->wifi_set_country_code);
     notSupported(fn->wifi_get_firmware_memory_dump);
-    notSupported(fn->wifi_set_log_handler);
     notSupported(fn->wifi_reset_log_handler);
-    notSupported(fn->wifi_get_ring_buffers_status);
-    notSupported(fn->wifi_get_logger_supported_feature_set);
-    notSupported(fn->wifi_get_ring_data);
     notSupported(fn->wifi_start_rssi_monitoring);
     notSupported(fn->wifi_stop_rssi_monitoring);
-    notSupported(fn->wifi_configure_nd_offload);
     notSupported(fn->wifi_start_sending_offloaded_packet);
     notSupported(fn->wifi_stop_sending_offloaded_packet);
-    notSupported(fn->wifi_start_pkt_fate_monitoring);
-    notSupported(fn->wifi_get_tx_pkt_fates);
-    notSupported(fn->wifi_get_rx_pkt_fates);
-    notSupported(fn->wifi_get_packet_filter_capabilities);
     notSupported(fn->wifi_set_packet_filter);
 
     return WIFI_SUCCESS;