From dbd83ef5855a40840278fa865d23b31cc911cd2e Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 20 Jun 2017 12:05:40 -0700 Subject: wifi(implementation): Create 1.1 interface package 1. Move the implementation in 1.0/default to 1.1/default. 2. Move all of the implementation to android::hardware::V1_1::implementation namespace. 3. All of the header files include the android::hardware::V1_0 namespace so that it can access the types from 1.0 package. ("using namespace" is against Google style guide though :(). The other option to prefix each 1.0 type with the namespace name. For example: V1_0::WifiStatus. 4. Added the implementation of the new 1.1 method IWifiChip.setTxPowerLimit(). 4. The executable name and the .rc still has 1.0 name in it to avoid changing all the device.mk files. TODO: Hookup to the new legacy HAL API. Bug: 62437848 Test: mmm -j128 hardware/interfaces/wifi/1.1/default/ Test: Device boots up and able to connect to wifi networks. Test: New VTS tests passes Change-Id: Ib36282939e70b064f246041a03d8870f5cb6410e --- wifi/1.1/default/Android.mk | 52 + wifi/1.1/default/THREADING.README | 35 + .../default/android.hardware.wifi@1.0-service.rc | 4 + wifi/1.1/default/hidl_callback_util.h | 121 ++ wifi/1.1/default/hidl_return_util.h | 114 + wifi/1.1/default/hidl_struct_util.cpp | 2183 ++++++++++++++++++++ wifi/1.1/default/hidl_struct_util.h | 170 ++ wifi/1.1/default/hidl_sync_util.cpp | 39 + wifi/1.1/default/hidl_sync_util.h | 37 + wifi/1.1/default/service.cpp | 44 + wifi/1.1/default/wifi.cpp | 201 ++ wifi/1.1/default/wifi.h | 88 + wifi/1.1/default/wifi_ap_iface.cpp | 106 + wifi/1.1/default/wifi_ap_iface.h | 72 + wifi/1.1/default/wifi_chip.cpp | 904 ++++++++ wifi/1.1/default/wifi_chip.h | 215 ++ wifi/1.1/default/wifi_feature_flags.h | 41 + wifi/1.1/default/wifi_legacy_hal.cpp | 1322 ++++++++++++ wifi/1.1/default/wifi_legacy_hal.h | 306 +++ wifi/1.1/default/wifi_legacy_hal_stubs.cpp | 142 ++ wifi/1.1/default/wifi_legacy_hal_stubs.h | 36 + wifi/1.1/default/wifi_mode_controller.cpp | 86 + wifi/1.1/default/wifi_mode_controller.h | 61 + wifi/1.1/default/wifi_nan_iface.cpp | 769 +++++++ wifi/1.1/default/wifi_nan_iface.h | 141 ++ wifi/1.1/default/wifi_p2p_iface.cpp | 70 + wifi/1.1/default/wifi_p2p_iface.h | 65 + wifi/1.1/default/wifi_rtt_controller.cpp | 297 +++ wifi/1.1/default/wifi_rtt_controller.h | 105 + wifi/1.1/default/wifi_sta_iface.cpp | 629 ++++++ wifi/1.1/default/wifi_sta_iface.h | 168 ++ wifi/1.1/default/wifi_status_util.cpp | 106 + wifi/1.1/default/wifi_status_util.h | 45 + wifi/1.1/vts/functional/Android.bp | 39 + .../vts/functional/VtsHalWifiV1_1TargetTest.cpp | 29 + wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp | 94 + 36 files changed, 8936 insertions(+) create mode 100644 wifi/1.1/default/Android.mk create mode 100644 wifi/1.1/default/THREADING.README create mode 100644 wifi/1.1/default/android.hardware.wifi@1.0-service.rc create mode 100644 wifi/1.1/default/hidl_callback_util.h create mode 100644 wifi/1.1/default/hidl_return_util.h create mode 100644 wifi/1.1/default/hidl_struct_util.cpp create mode 100644 wifi/1.1/default/hidl_struct_util.h create mode 100644 wifi/1.1/default/hidl_sync_util.cpp create mode 100644 wifi/1.1/default/hidl_sync_util.h create mode 100644 wifi/1.1/default/service.cpp create mode 100644 wifi/1.1/default/wifi.cpp create mode 100644 wifi/1.1/default/wifi.h create mode 100644 wifi/1.1/default/wifi_ap_iface.cpp create mode 100644 wifi/1.1/default/wifi_ap_iface.h create mode 100644 wifi/1.1/default/wifi_chip.cpp create mode 100644 wifi/1.1/default/wifi_chip.h create mode 100644 wifi/1.1/default/wifi_feature_flags.h create mode 100644 wifi/1.1/default/wifi_legacy_hal.cpp create mode 100644 wifi/1.1/default/wifi_legacy_hal.h create mode 100644 wifi/1.1/default/wifi_legacy_hal_stubs.cpp create mode 100644 wifi/1.1/default/wifi_legacy_hal_stubs.h create mode 100644 wifi/1.1/default/wifi_mode_controller.cpp create mode 100644 wifi/1.1/default/wifi_mode_controller.h create mode 100644 wifi/1.1/default/wifi_nan_iface.cpp create mode 100644 wifi/1.1/default/wifi_nan_iface.h create mode 100644 wifi/1.1/default/wifi_p2p_iface.cpp create mode 100644 wifi/1.1/default/wifi_p2p_iface.h create mode 100644 wifi/1.1/default/wifi_rtt_controller.cpp create mode 100644 wifi/1.1/default/wifi_rtt_controller.h create mode 100644 wifi/1.1/default/wifi_sta_iface.cpp create mode 100644 wifi/1.1/default/wifi_sta_iface.h create mode 100644 wifi/1.1/default/wifi_status_util.cpp create mode 100644 wifi/1.1/default/wifi_status_util.h create mode 100644 wifi/1.1/vts/functional/Android.bp create mode 100644 wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp create mode 100644 wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp (limited to 'wifi/1.1') diff --git a/wifi/1.1/default/Android.mk b/wifi/1.1/default/Android.mk new file mode 100644 index 000000000..575842230 --- /dev/null +++ b/wifi/1.1/default/Android.mk @@ -0,0 +1,52 @@ +# Copyright (C) 2016 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. +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.wifi@1.0-service +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CPPFLAGS := -Wall -Werror -Wextra +ifdef WIFI_HIDL_FEATURE_AWARE +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE +endif +LOCAL_SRC_FILES := \ + hidl_struct_util.cpp \ + hidl_sync_util.cpp \ + service.cpp \ + wifi.cpp \ + wifi_ap_iface.cpp \ + wifi_chip.cpp \ + wifi_legacy_hal.cpp \ + wifi_legacy_hal_stubs.cpp \ + wifi_mode_controller.cpp \ + wifi_nan_iface.cpp \ + wifi_p2p_iface.cpp \ + wifi_rtt_controller.cpp \ + wifi_sta_iface.cpp \ + wifi_status_util.cpp +LOCAL_SHARED_LIBRARIES := \ + android.hardware.wifi@1.0 \ + android.hardware.wifi@1.1 \ + libbase \ + libcutils \ + libhidlbase \ + libhidltransport \ + liblog \ + libnl \ + libutils \ + libwifi-hal \ + libwifi-system-iface +LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc +include $(BUILD_EXECUTABLE) diff --git a/wifi/1.1/default/THREADING.README b/wifi/1.1/default/THREADING.README new file mode 100644 index 000000000..8366ca020 --- /dev/null +++ b/wifi/1.1/default/THREADING.README @@ -0,0 +1,35 @@ +Vendor HAL Threading Model +========================== +The vendor HAL service has two threads: +1. HIDL thread: This is the main thread which processes all the incoming HIDL +RPC's. +2. Legacy HAL event loop thread: This is the thread forked off for processing +the legacy HAL event loop (wifi_event_loop()). This thread is used to process +any asynchronous netlink events posted by the driver. Any asynchronous +callbacks passed to the legacy HAL API's are invoked on this thread. + +Synchronization Concerns +======================== +wifi_legacy_hal.cpp has a bunch of global "C" style functions to handle the +legacy callbacks. Each of these "C" style function invokes a corresponding +"std::function" version of the callback which does the actual processing. +The variables holding these "std::function" callbacks are reset from the HIDL +thread when they are no longer used. For example: stopGscan() will reset the +corresponding "on_gscan_*" callback variables which were set when startGscan() +was invoked. This is not thread safe since these callback variables are +accesed from the legacy hal event loop thread as well. + +Synchronization Solution +======================== +Adding a global lock seems to be the most trivial solution to the problem. +a) All of the asynchronous "C" style callbacks will acquire the global lock +before invoking the corresponding "std::function" callback variables. +b) All of the HIDL methods will also acquire the global lock before processing +(in hidl_return_util::validateAndCall()). + +Note: It's important that we only acquire the global lock for asynchronous +callbacks, because there is no guarantee (or documentation to clarify) that the +synchronous callbacks are invoked on the same invocation thread. If that is not +the case in some implementation, we will end up deadlocking the system since the +HIDL thread would have acquired the global lock which is needed by the +synchronous callback executed on the legacy hal event loop thread. diff --git a/wifi/1.1/default/android.hardware.wifi@1.0-service.rc b/wifi/1.1/default/android.hardware.wifi@1.0-service.rc new file mode 100644 index 000000000..696b1f933 --- /dev/null +++ b/wifi/1.1/default/android.hardware.wifi@1.0-service.rc @@ -0,0 +1,4 @@ +service wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service + class hal + user wifi + group wifi gps diff --git a/wifi/1.1/default/hidl_callback_util.h b/wifi/1.1/default/hidl_callback_util.h new file mode 100644 index 000000000..fb1362225 --- /dev/null +++ b/wifi/1.1/default/hidl_callback_util.h @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#ifndef HIDL_CALLBACK_UTIL_H_ +#define HIDL_CALLBACK_UTIL_H_ + +#include + +#include + +namespace { +// Type of callback invoked by the death handler. +using on_death_cb_function = std::function; + +// Private class used to keep track of death of individual +// callbacks stored in HidlCallbackHandler. +template +class HidlDeathHandler : public android::hardware::hidl_death_recipient { + public: + HidlDeathHandler(const on_death_cb_function& user_cb_function) + : cb_function_(user_cb_function) {} + ~HidlDeathHandler() = default; + + // Death notification for callbacks. + void serviceDied( + uint64_t cookie, + const android::wp& /* who */) override { + cb_function_(cookie); + } + + private: + on_death_cb_function cb_function_; + + DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler); +}; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_callback_util { +template +// Provides a class to manage callbacks for the various HIDL interfaces and +// handle the death of the process hosting each callback. +class HidlCallbackHandler { + public: + HidlCallbackHandler() + : death_handler_(new HidlDeathHandler( + std::bind(&HidlCallbackHandler::onObjectDeath, + this, + std::placeholders::_1))) {} + ~HidlCallbackHandler() = default; + + bool addCallback(const sp& cb) { + // TODO(b/33818800): Can't compare proxies yet. So, use the cookie + // (callback proxy's raw pointer) to track the death of individual clients. + uint64_t cookie = reinterpret_cast(cb.get()); + if (cb_set_.find(cb) != cb_set_.end()) { + LOG(WARNING) << "Duplicate death notification registration"; + return true; + } + if (!cb->linkToDeath(death_handler_, cookie)) { + LOG(ERROR) << "Failed to register death notification"; + return false; + } + cb_set_.insert(cb); + return true; + } + + const std::set>& getCallbacks() { return cb_set_; } + + // Death notification for callbacks. + void onObjectDeath(uint64_t cookie) { + CallbackType* cb = reinterpret_cast(cookie); + const auto& iter = cb_set_.find(cb); + if (iter == cb_set_.end()) { + LOG(ERROR) << "Unknown callback death notification received"; + return; + } + cb_set_.erase(iter); + LOG(DEBUG) << "Dead callback removed from list"; + } + + void invalidate() { + for (const sp& cb : cb_set_) { + if (!cb->unlinkToDeath(death_handler_)) { + LOG(ERROR) << "Failed to deregister death notification"; + } + } + cb_set_.clear(); + } + + private: + std::set> cb_set_; + sp> death_handler_; + + DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); +}; + +} // namespace hidl_callback_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_CALLBACK_UTIL_H_ diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h new file mode 100644 index 000000000..2f95c23d7 --- /dev/null +++ b/wifi/1.1/default/hidl_return_util.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef HIDL_RETURN_UTIL_H_ +#define HIDL_RETURN_UTIL_H_ + +#include "hidl_sync_util.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_return_util { +using namespace android::hardware::wifi::V1_0; + +/** + * These utility functions are used to invoke a method on the provided + * HIDL interface object. + * These functions checks if the provided HIDL interface object is valid. + * a) if valid, Invokes the corresponding internal implementation function of + * the HIDL method. It then invokes the HIDL continuation callback with + * the status and any returned values. + * b) if invalid, invokes the HIDL continuation callback with the + * provided error status and default values. + */ +// Use for HIDL methods which return only an instance of WifiStatus. +template +Return validateAndCall( + ObjT* obj, + WifiStatusCode status_code_if_invalid, + WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(std::forward(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and a single return +// value. +template +Return validateAndCall( + ObjT* obj, + WifiStatusCode status_code_if_invalid, + WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_pair = (obj->*work)(std::forward(args)...); + const WifiStatus& status = std::get<0>(ret_pair); + const auto& ret_value = std::get<1>(ret_pair); + hidl_cb(status, ret_value); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference::type()); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and 2 return +// values. +template +Return validateAndCall( + ObjT* obj, + WifiStatusCode status_code_if_invalid, + WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_tuple = (obj->*work)(std::forward(args)...); + const WifiStatus& status = std::get<0>(ret_tuple); + const auto& ret_value1 = std::get<1>(ret_tuple); + const auto& ret_value2 = std::get<2>(ret_tuple); + hidl_cb(status, ret_value1, ret_value2); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference::type(), + typename std::remove_reference::type()); + } + return Void(); +} + +} // namespace hidl_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_RETURN_UTIL_H_ diff --git a/wifi/1.1/default/hidl_struct_util.cpp b/wifi/1.1/default/hidl_struct_util.cpp new file mode 100644 index 000000000..e40a7d8fd --- /dev/null +++ b/wifi/1.1/default/hidl_struct_util.cpp @@ -0,0 +1,2183 @@ +/* + * Copyright (C) 2016 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 +#include + +#include "hidl_struct_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_struct_util { + +hidl_string safeConvertChar(const char* str, size_t max_len) { + const char* c = str; + size_t size = 0; + while (*c && (unsigned char)*c < 128 && size < max_len) { + ++size; + ++c; + } + return hidl_string(str, size); +} + +IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability( + uint32_t feature) { + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP; + case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP; + case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT; + case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT; + case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask +convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED: + return HidlStaIfaceCaps::DEBUG_PACKET_FATE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask +convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case WIFI_FEATURE_GSCAN: + return HidlStaIfaceCaps::BACKGROUND_SCAN; + case WIFI_FEATURE_LINK_LAYER_STATS: + return HidlStaIfaceCaps::LINK_LAYER_STATS; + case WIFI_FEATURE_RSSI_MONITOR: + return HidlStaIfaceCaps::RSSI_MONITOR; + case WIFI_FEATURE_CONTROL_ROAMING: + return HidlStaIfaceCaps::CONTROL_ROAMING; + case WIFI_FEATURE_IE_WHITELIST: + return HidlStaIfaceCaps::PROBE_IE_WHITELIST; + case WIFI_FEATURE_SCAN_RAND: + return HidlStaIfaceCaps::SCAN_RAND; + case WIFI_FEATURE_INFRA_5G: + return HidlStaIfaceCaps::STA_5G; + case WIFI_FEATURE_HOTSPOT: + return HidlStaIfaceCaps::HOTSPOT; + case WIFI_FEATURE_PNO: + return HidlStaIfaceCaps::PNO; + case WIFI_FEATURE_TDLS: + return HidlStaIfaceCaps::TDLS; + case WIFI_FEATURE_TDLS_OFFCHANNEL: + return HidlStaIfaceCaps::TDLS_OFFCHANNEL; + case WIFI_FEATURE_CONFIG_NDO: + return HidlStaIfaceCaps::ND_OFFLOAD; + case WIFI_FEATURE_MKEEP_ALIVE: + return HidlStaIfaceCaps::KEEP_ALIVE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +bool convertLegacyFeaturesToHidlChipCapabilities( + uint32_t legacy_logger_feature_set, uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature); + } + } + // There are no flags for these 3 in the legacy feature set. Adding them to + // the set because all the current devices support it. + *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA; + *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS; + *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS; + return true; +} + +WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl( + uint32_t flag) { + switch (flag) { + case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES: + return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES; + case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES: + return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES; + }; + CHECK(false) << "Unknown legacy flag: " << flag; + return {}; +} + +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status) { + if (!hidl_status) { + return false; + } + *hidl_status = {}; + hidl_status->ringName = safeConvertChar(reinterpret_cast(legacy_status.name), + sizeof(legacy_status.name)); + hidl_status->flags = 0; + for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, + WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) { + if (flag & legacy_status.flags) { + hidl_status->flags |= + static_cast::type>( + convertLegacyDebugRingBufferFlagsToHidl(flag)); + } + } + hidl_status->ringId = legacy_status.ring_id; + hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size; + // Calculate free size of the ring the buffer. We don't need to send the + // exact read/write pointers that were there in the legacy HAL interface. + if (legacy_status.written_bytes >= legacy_status.read_bytes) { + hidl_status->freeSizeInBytes = + legacy_status.ring_buffer_byte_size - + (legacy_status.written_bytes - legacy_status.read_bytes); + } else { + hidl_status->freeSizeInBytes = + legacy_status.read_bytes - legacy_status.written_bytes; + } + hidl_status->verboseLevel = legacy_status.verbose_level; + return true; +} + +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector& legacy_status_vec, + std::vector* hidl_status_vec) { + if (!hidl_status_vec) { + return false; + } + *hidl_status_vec = {}; + for (const auto& legacy_status : legacy_status_vec) { + WifiDebugRingBufferStatus hidl_status; + if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status, + &hidl_status)) { + return false; + } + hidl_status_vec->push_back(hidl_status); + } + return true; +} + +bool convertLegacyWakeReasonStatsToHidl( + const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + hidl_stats->totalCmdEventWakeCnt = + legacy_stats.wake_reason_cnt.total_cmd_event_wake; + hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt; + hidl_stats->totalDriverFwLocalWakeCnt = + legacy_stats.wake_reason_cnt.total_driver_fw_local_wake; + hidl_stats->driverFwLocalWakeCntPerType = + legacy_stats.driver_fw_local_wake_cnt; + hidl_stats->totalRxPacketWakeCnt = + legacy_stats.wake_reason_cnt.total_rx_data_wake; + hidl_stats->rxPktWakeDetails.rxUnicastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt; + hidl_stats->rxPktWakeDetails.rxMulticastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt; + hidl_stats->rxPktWakeDetails.rxBroadcastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .ipv4_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .ipv6_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .other_rx_multicast_addr_cnt; + hidl_stats->rxIcmpPkWakeDetails.icmpPkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ra = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra; + hidl_stats->rxIcmpPkWakeDetails.icmp6Na = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ns = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns; + return true; +} + +bool convertLegacyFeaturesToHidlStaCapabilities( + uint32_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + *hidl_caps = 0; + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature); + } + } + for (const auto feature : {WIFI_FEATURE_GSCAN, + WIFI_FEATURE_LINK_LAYER_STATS, + WIFI_FEATURE_RSSI_MONITOR, + WIFI_FEATURE_CONTROL_ROAMING, + WIFI_FEATURE_IE_WHITELIST, + WIFI_FEATURE_SCAN_RAND, + WIFI_FEATURE_INFRA_5G, + WIFI_FEATURE_HOTSPOT, + WIFI_FEATURE_PNO, + WIFI_FEATURE_TDLS, + WIFI_FEATURE_TDLS_OFFCHANNEL, + WIFI_FEATURE_CONFIG_NDO, + WIFI_FEATURE_MKEEP_ALIVE}) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature); + } + } + // There is no flag for this one in the legacy feature set. Adding it to the + // set because all the current devices support it. + *hidl_caps |= HidlStaIfaceCaps::APF; + return true; +} + +bool convertLegacyApfCapabilitiesToHidl( + const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->version = legacy_caps.version; + hidl_caps->maxLength = legacy_caps.max_len; + return true; +} + +uint8_t convertHidlGscanReportEventFlagToLegacy( + StaBackgroundScanBucketEventReportSchemeMask hidl_flag) { + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + switch (hidl_flag) { + case HidlFlag::EACH_SCAN: + return REPORT_EVENTS_EACH_SCAN; + case HidlFlag::FULL_RESULTS: + return REPORT_EVENTS_FULL_RESULTS; + case HidlFlag::NO_BATCH: + return REPORT_EVENTS_NO_BATCH; + }; + CHECK(false); +} + +StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) { + switch (legacy_flag) { + case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED: + return StaScanDataFlagMask::INTERRUPTED; + }; + CHECK(false) << "Unknown legacy flag: " << legacy_flag; + // To silence the compiler warning about reaching the end of non-void + // function. + return {}; +} + +bool convertLegacyGscanCapabilitiesToHidl( + const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size; + hidl_caps->maxBuckets = legacy_caps.max_scan_buckets; + hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan; + hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold; + return true; +} + +legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band) { + switch (band) { + case WifiBand::BAND_UNSPECIFIED: + return legacy_hal::WIFI_BAND_UNSPECIFIED; + case WifiBand::BAND_24GHZ: + return legacy_hal::WIFI_BAND_BG; + case WifiBand::BAND_5GHZ: + return legacy_hal::WIFI_BAND_A; + case WifiBand::BAND_5GHZ_DFS: + return legacy_hal::WIFI_BAND_A_DFS; + case WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_A_WITH_DFS; + case WifiBand::BAND_24GHZ_5GHZ: + return legacy_hal::WIFI_BAND_ABG; + case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_ABG_WITH_DFS; + }; + CHECK(false); +} + +bool convertHidlGscanParamsToLegacy( + const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params) { + if (!legacy_scan_params) { + return false; + } + *legacy_scan_params = {}; + legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs; + legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan; + legacy_scan_params->report_threshold_percent = + hidl_scan_params.reportThresholdPercent; + legacy_scan_params->report_threshold_num_scans = + hidl_scan_params.reportThresholdNumScans; + if (hidl_scan_params.buckets.size() > MAX_BUCKETS) { + return false; + } + legacy_scan_params->num_buckets = hidl_scan_params.buckets.size(); + for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); + bucket_idx++) { + const StaBackgroundScanBucketParameters& hidl_bucket_spec = + hidl_scan_params.buckets[bucket_idx]; + legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec = + legacy_scan_params->buckets[bucket_idx]; + if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) { + return false; + } + legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx; + legacy_bucket_spec.band = + convertHidlWifiBandToLegacy(hidl_bucket_spec.band); + legacy_bucket_spec.period = hidl_bucket_spec.periodInMs; + legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs; + legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase; + legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount; + legacy_bucket_spec.report_events = 0; + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + for (const auto flag : + {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) { + if (hidl_bucket_spec.eventReportScheme & + static_cast::type>(flag)) { + legacy_bucket_spec.report_events |= + convertHidlGscanReportEventFlagToLegacy(flag); + } + } + if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) { + return false; + } + legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size(); + for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size(); + freq_idx++) { + legacy_bucket_spec.channels[freq_idx].channel = + hidl_bucket_spec.frequencies[freq_idx]; + } + } + return true; +} + +bool convertLegacyIeToHidl( + const legacy_hal::wifi_information_element& legacy_ie, + WifiInformationElement* hidl_ie) { + if (!hidl_ie) { + return false; + } + *hidl_ie = {}; + hidl_ie->id = legacy_ie.id; + hidl_ie->data = + std::vector(legacy_ie.data, legacy_ie.data + legacy_ie.len); + return true; +} + +bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, + uint32_t ie_blob_len, + std::vector* hidl_ies) { + if (!ie_blob || !hidl_ies) { + return false; + } + *hidl_ies = {}; + const uint8_t* ies_begin = ie_blob; + const uint8_t* ies_end = ie_blob + ie_blob_len; + const uint8_t* next_ie = ies_begin; + using wifi_ie = legacy_hal::wifi_information_element; + constexpr size_t kIeHeaderLen = sizeof(wifi_ie); + // Each IE should atleast have the header (i.e |id| & |len| fields). + while (next_ie + kIeHeaderLen <= ies_end) { + const wifi_ie& legacy_ie = (*reinterpret_cast(next_ie)); + uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len; + if (next_ie + curr_ie_len > ies_end) { + LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void *)next_ie + << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void *)ies_end; + break; + } + WifiInformationElement hidl_ie; + if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) { + LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id + << ", len: " << legacy_ie.len; + break; + } + hidl_ies->push_back(std::move(hidl_ie)); + next_ie += curr_ie_len; + } + // Check if the blob has been fully consumed. + if (next_ie != ies_end) { + LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void *)next_ie + << ", IEs End: " << (void *)ies_end; + } + return true; +} + +bool convertLegacyGscanResultToHidl( + const legacy_hal::wifi_scan_result& legacy_scan_result, + bool has_ie_data, + StaScanResult* hidl_scan_result) { + if (!hidl_scan_result) { + return false; + } + *hidl_scan_result = {}; + hidl_scan_result->timeStampInUs = legacy_scan_result.ts; + hidl_scan_result->ssid = std::vector( + legacy_scan_result.ssid, + legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid, + sizeof(legacy_scan_result.ssid) - 1)); + memcpy(hidl_scan_result->bssid.data(), + legacy_scan_result.bssid, + hidl_scan_result->bssid.size()); + hidl_scan_result->frequency = legacy_scan_result.channel; + hidl_scan_result->rssi = legacy_scan_result.rssi; + hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period; + hidl_scan_result->capability = legacy_scan_result.capability; + if (has_ie_data) { + std::vector ies; + if (!convertLegacyIeBlobToHidl( + reinterpret_cast(legacy_scan_result.ie_data), + legacy_scan_result.ie_length, + &ies)) { + return false; + } + hidl_scan_result->informationElements = std::move(ies); + } + return true; +} + +bool convertLegacyCachedGscanResultsToHidl( + const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result, + StaScanData* hidl_scan_data) { + if (!hidl_scan_data) { + return false; + } + *hidl_scan_data = {}; + hidl_scan_data->flags = 0; + for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) { + if (legacy_cached_scan_result.flags & flag) { + hidl_scan_data->flags |= + static_cast::type>( + convertLegacyGscanDataFlagToHidl(flag)); + } + } + hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned; + + CHECK(legacy_cached_scan_result.num_results >= 0 && + legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN); + std::vector hidl_scan_results; + for (int32_t result_idx = 0; + result_idx < legacy_cached_scan_result.num_results; + result_idx++) { + StaScanResult hidl_scan_result; + if (!convertLegacyGscanResultToHidl( + legacy_cached_scan_result.results[result_idx], + false, + &hidl_scan_result)) { + return false; + } + hidl_scan_results.push_back(hidl_scan_result); + } + hidl_scan_data->results = std::move(hidl_scan_results); + return true; +} + +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector& + legacy_cached_scan_results, + std::vector* hidl_scan_datas) { + if (!hidl_scan_datas) { + return false; + } + *hidl_scan_datas = {}; + for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) { + StaScanData hidl_scan_data; + if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result, + &hidl_scan_data)) { + return false; + } + hidl_scan_datas->push_back(hidl_scan_data); + } + return true; +} + +WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl( + legacy_hal::wifi_tx_packet_fate fate) { + switch (fate) { + case legacy_hal::TX_PKT_FATE_ACKED: + return WifiDebugTxPacketFate::ACKED; + case legacy_hal::TX_PKT_FATE_SENT: + return WifiDebugTxPacketFate::SENT; + case legacy_hal::TX_PKT_FATE_FW_QUEUED: + return WifiDebugTxPacketFate::FW_QUEUED; + case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugTxPacketFate::FW_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugTxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugTxPacketFate::FW_DROP_OTHER; + case legacy_hal::TX_PKT_FATE_DRV_QUEUED: + return WifiDebugTxPacketFate::DRV_QUEUED; + case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugTxPacketFate::DRV_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugTxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugTxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl( + legacy_hal::wifi_rx_packet_fate fate) { + switch (fate) { + case legacy_hal::RX_PKT_FATE_SUCCESS: + return WifiDebugRxPacketFate::SUCCESS; + case legacy_hal::RX_PKT_FATE_FW_QUEUED: + return WifiDebugRxPacketFate::FW_QUEUED; + case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER: + return WifiDebugRxPacketFate::FW_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugRxPacketFate::FW_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugRxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugRxPacketFate::FW_DROP_OTHER; + case legacy_hal::RX_PKT_FATE_DRV_QUEUED: + return WifiDebugRxPacketFate::DRV_QUEUED; + case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER: + return WifiDebugRxPacketFate::DRV_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugRxPacketFate::DRV_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugRxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugRxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl( + legacy_hal::frame_type type) { + switch (type) { + case legacy_hal::FRAME_TYPE_UNKNOWN: + return WifiDebugPacketFateFrameType::UNKNOWN; + case legacy_hal::FRAME_TYPE_ETHERNET_II: + return WifiDebugPacketFateFrameType::ETHERNET_II; + case legacy_hal::FRAME_TYPE_80211_MGMT: + return WifiDebugPacketFateFrameType::MGMT_80211; + }; + CHECK(false) << "Unknown legacy frame type: " << type; +} + +bool convertLegacyDebugPacketFateFrameToHidl( + const legacy_hal::frame_info& legacy_frame, + WifiDebugPacketFateFrameInfo* hidl_frame) { + if (!hidl_frame) { + return false; + } + *hidl_frame = {}; + hidl_frame->frameType = + convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type); + hidl_frame->frameLen = legacy_frame.frame_len; + hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec; + hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec; + const uint8_t* frame_begin = reinterpret_cast( + legacy_frame.frame_content.ethernet_ii_bytes); + hidl_frame->frameContent = + std::vector(frame_begin, frame_begin + legacy_frame.frame_len); + return true; +} + +bool convertLegacyDebugTxPacketFateToHidl( + const legacy_hal::wifi_tx_report& legacy_fate, + WifiDebugTxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, + &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugTxPacketFateReport hidl_fate; + if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyDebugRxPacketFateToHidl( + const legacy_hal::wifi_rx_report& legacy_fate, + WifiDebugRxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, + &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugRxPacketFateReport hidl_fate; + if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyLinkLayerStatsToHidl( + const legacy_hal::LinkLayerStats& legacy_stats, + StaLinkLayerStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + // iface legacy_stats conversion. + hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx; + hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + hidl_stats->iface.wmeBePktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + hidl_stats->iface.wmeBePktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + hidl_stats->iface.wmeBePktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + hidl_stats->iface.wmeBePktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; + hidl_stats->iface.wmeBkPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + hidl_stats->iface.wmeBkPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + hidl_stats->iface.wmeBkPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + hidl_stats->iface.wmeBkPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; + hidl_stats->iface.wmeViPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + hidl_stats->iface.wmeViPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + hidl_stats->iface.wmeViPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + hidl_stats->iface.wmeViPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; + hidl_stats->iface.wmeVoPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + hidl_stats->iface.wmeVoPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + hidl_stats->iface.wmeVoPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + hidl_stats->iface.wmeVoPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + // radio legacy_stats conversion. + std::vector hidl_radios_stats; + for (const auto& legacy_radio_stats : legacy_stats.radios) { + StaLinkLayerRadioStats hidl_radio_stats; + hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time; + hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time; + hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time; + hidl_radio_stats.onTimeInMsForScan = legacy_radio_stats.stats.on_time_scan; + hidl_radio_stats.txTimeInMsPerLevel = legacy_radio_stats.tx_time_per_levels; + hidl_radios_stats.push_back(hidl_radio_stats); + } + hidl_stats->radios = hidl_radios_stats; + // Timestamp in the HAL wrapper here since it's not provided in the legacy + // HAL API. + hidl_stats->timeStampInMs = uptimeMillis(); + return true; +} + +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size; + hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size; + return true; +} + +bool convertHidlRoamingConfigToLegacy( + const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID || + hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) { + return false; + } + legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size(); + uint32_t i = 0; + for (const auto& bssid : hidl_config.bssidBlacklist) { + CHECK(bssid.size() == sizeof(legacy_hal::mac_addr)); + memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size()); + } + legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size(); + i = 0; + for (const auto& ssid : hidl_config.ssidWhitelist) { + CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str)); + legacy_config->whitelist_ssid[i].length = ssid.size(); + memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), ssid.size()); + i++; + } + return true; +} + +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy( + StaRoamingState state) { + switch (state) { + case StaRoamingState::ENABLED: + return legacy_hal::ROAMING_ENABLE; + case StaRoamingState::DISABLED: + return legacy_hal::ROAMING_DISABLE; + }; + CHECK(false); +} + +legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) { + switch (type) { + case NanMatchAlg::MATCH_ONCE: + return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE; + case NanMatchAlg::MATCH_CONTINUOUS: + return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS; + case NanMatchAlg::MATCH_NEVER: + return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER; + } + CHECK(false); +} + +legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(NanPublishType type) { + switch (type) { + case NanPublishType::UNSOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED; + case NanPublishType::SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED; + case NanPublishType::UNSOLICITED_SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED; + } + CHECK(false); +} + +legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) { + switch (type) { + case NanTxType::BROADCAST: + return legacy_hal::NAN_TX_TYPE_BROADCAST; + case NanTxType::UNICAST: + return legacy_hal::NAN_TX_TYPE_UNICAST; + } + CHECK(false); +} + +legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(NanSubscribeType type) { + switch (type) { + case NanSubscribeType::PASSIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE; + case NanSubscribeType::ACTIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE; + } + CHECK(false); +} + +legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) { + switch (type) { + case NanSrfType::BLOOM_FILTER: + return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER; + case NanSrfType::PARTIAL_MAC_ADDR: + return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR; + } + CHECK(false); +} + +legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy( + NanDataPathChannelCfg type) { + switch (type) { + case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED: + return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED; + case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP: + return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP; + case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP: + return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP; + } + CHECK(false); +} + +NanStatusType convertLegacyNanStatusTypeToHidl( + legacy_hal::NanStatusType type) { + switch (type) { + case legacy_hal::NAN_STATUS_SUCCESS: + return NanStatusType::SUCCESS; + case legacy_hal::NAN_STATUS_INTERNAL_FAILURE: + return NanStatusType::INTERNAL_FAILURE; + case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE: + return NanStatusType::PROTOCOL_FAILURE; + case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID: + return NanStatusType::INVALID_SESSION_ID; + case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE: + return NanStatusType::NO_RESOURCES_AVAILABLE; + case legacy_hal::NAN_STATUS_INVALID_PARAM: + return NanStatusType::INVALID_ARGS; + case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID: + return NanStatusType::INVALID_PEER_ID; + case legacy_hal::NAN_STATUS_INVALID_NDP_ID: + return NanStatusType::INVALID_NDP_ID; + case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED: + return NanStatusType::NAN_NOT_ALLOWED; + case legacy_hal::NAN_STATUS_NO_OTA_ACK: + return NanStatusType::NO_OTA_ACK; + case legacy_hal::NAN_STATUS_ALREADY_ENABLED: + return NanStatusType::ALREADY_ENABLED; + case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL: + return NanStatusType::FOLLOWUP_TX_QUEUE_FULL; + case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED; + } + CHECK(false); +} + +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, + WifiNanStatus* wifiNanStatus) { + wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type); + wifiNanStatus->description = safeConvertChar(str, max_len); +} + +bool convertHidlNanEnableRequestToLegacy( + const NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->config_2dot4g_support = 1; + legacy_request->support_2dot4g_val = hidl_request.operateInBand[ + (size_t) NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_support_5g = 1; + legacy_request->support_5g_val = hidl_request.operateInBand[(size_t) NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_hop_count_limit = 1; + legacy_request->hop_count_limit_val = hidl_request.hopCountMax; + legacy_request->master_pref = hidl_request.configParams.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon_val = + (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0) + | (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) + | (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = hidl_request.configParams.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.configParams.macAddressRandomizationIntervalSec; + legacy_request->config_2dot4g_rssi_close = 1; + if (hidl_request.configParams.bandSpecificConfig.size() != 2) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: bandSpecificConfig.size() != 2"; + return false; + } + legacy_request->rssi_close_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity; + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = hidl_request.configParams + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = hidl_request.configParams + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].discoveryWindowIntervalVal; + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle; + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = hidl_request.configParams + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = hidl_request.configParams + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].discoveryWindowIntervalVal; + if (hidl_request.debugConfigs.validClusterIdVals) { + legacy_request->cluster_low = hidl_request.debugConfigs.clusterIdBottomRangeVal; + legacy_request->cluster_high = hidl_request.debugConfigs.clusterIdTopRangeVal; + } else { // need 'else' since not configurable in legacy HAL + legacy_request->cluster_low = 0x0000; + legacy_request->cluster_high = 0xFFFF; + } + legacy_request->config_intf_addr = hidl_request.debugConfigs.validIntfAddrVal; + memcpy(legacy_request->intf_addr_val, hidl_request.debugConfigs.intfAddrVal.data(), 6); + legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal; + legacy_request->oui_val = hidl_request.debugConfigs.ouiVal; + legacy_request->config_random_factor_force = hidl_request.debugConfigs.validRandomFactorForceVal; + legacy_request->random_factor_force_val = hidl_request.debugConfigs.randomFactorForceVal; + legacy_request->config_hop_count_force = hidl_request.debugConfigs.validHopCountForceVal; + legacy_request->hop_count_force_val = hidl_request.debugConfigs.hopCountForceVal; + legacy_request->config_24g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_24g_val = + hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t) NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_5g_val = hidl_request.debugConfigs + .discoveryChannelMhzVal[(size_t) NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_2dot4g_val = hidl_request.debugConfigs + .useBeaconsInBandVal[(size_t) NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_5g_val = hidl_request.debugConfigs + .useBeaconsInBandVal[(size_t) NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_2dot4g_val = hidl_request.debugConfigs + .useSdfInBandVal[(size_t) NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_5g_val = hidl_request.debugConfigs + .useSdfInBandVal[(size_t) NanBandIndex::NAN_BAND_5GHZ]; + + return true; +} + +bool convertHidlNanPublishRequestToLegacy( + const NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->publish_match_indicator = + convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, + hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, + hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->recv_indication_cfg |= 0x8; + legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType; + if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType + == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len + < NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len + > NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType + != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ? + legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_cm = hidl_request.baseConfigs.distanceIngressCm; + legacy_request->ranging_cfg.distance_egress_cm = hidl_request.baseConfigs.distanceEgressCm; + legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired ? + legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->publish_type = convertHidlNanPublishTypeToLegacy(hidl_request.publishType); + legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType); + legacy_request->service_responder_policy = hidl_request.autoAcceptDataPathRequests ? + legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE; + + return true; +} + +bool convertHidlNanSubscribeRequestToLegacy( + const NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->subscribe_match_indicator = + convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << + "convertHidlNanSubscribeRequestToLegacy: sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, + hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, + hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType; + if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len + < NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len + > NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType + != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ? + legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_cm = hidl_request.baseConfigs.distanceIngressCm; + legacy_request->ranging_cfg.distance_egress_cm = hidl_request.baseConfigs.distanceEgressCm; + legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired ? + legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->subscribe_type = convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType); + legacy_request->serviceResponseFilter = convertHidlNanSrfTypeToLegacy(hidl_request.srfType); + legacy_request->serviceResponseInclude = hidl_request.srfRespondIfInAddressSet ? + legacy_hal::NAN_SRF_INCLUDE_RESPOND : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND; + legacy_request->useServiceResponseFilter = hidl_request.shouldUseSrf ? + legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF; + legacy_request->ssiRequiredForMatchIndication = hidl_request.isSsiRequiredForMatch ? + legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; + legacy_request->num_intf_addr_present = hidl_request.intfAddr.size(); + if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: num_intf_addr_present - too many"; + return false; + } + for (int i = 0; i < legacy_request->num_intf_addr_present; i++) { + memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), 6); + } + + return true; +} + +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_subscribe_id = hidl_request.discoverySessionId; + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->addr, hidl_request.addr.data(), 6); + legacy_request->priority = hidl_request.isHighPriority ? + legacy_hal::NAN_TX_PRIORITY_HIGH : legacy_hal::NAN_TX_PRIORITY_NORMAL; + legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow ? + legacy_hal::NAN_TRANSMIT_IN_DW : legacy_hal::NAN_TRANSMIT_IN_FAW; + legacy_request->service_specific_info_len = hidl_request.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << + "convertHidlNanTransmitFollowupRequestToLegacy: service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = hidl_request.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << + "convertHidlNanTransmitFollowupRequestToLegacy: sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->recv_indication_cfg = hidl_request.disableFollowupResultIndication ? 0x1 : 0x0; + + return true; +} + +bool convertHidlNanConfigRequestToLegacy( + const NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown defaults + legacy_request->master_pref = hidl_request.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon = (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) + | (hidl_request.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) + | (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.macAddressRandomizationIntervalSec; + /* TODO : missing + legacy_request->config_2dot4g_rssi_close = 1; + legacy_request->rssi_close_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity; + */ + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = hidl_request + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = hidl_request + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].discoveryWindowIntervalVal; + /* TODO: missing + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle; + */ + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = hidl_request + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = hidl_request + .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].discoveryWindowIntervalVal; + + return true; +} + +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6); + legacy_request->channel_request_type = + convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType); + legacy_request->channel = hidl_request.channel; + strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str()); + legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType + != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len + < NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len + > NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertHidlNanDataPathIndicationResponseToLegacy( + const NanRespondToDataPathIndicationRequest& hidl_request, + legacy_hal::NanDataPathIndicationResponse* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->rsp_code = hidl_request.acceptRequest ? + legacy_hal::NAN_DP_REQUEST_ACCEPT : legacy_hal::NAN_DP_REQUEST_REJECT; + legacy_request->ndp_instance_id = hidl_request.ndpInstanceId; + strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str()); + legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType + != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len + < NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len + > NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertLegacyNanResponseHeaderToHidl( + const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus) { + if (!wifiNanStatus) { + LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null"; + return false; + } + *wifiNanStatus = {}; + + convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error, + sizeof(legacy_response.nan_error), wifiNanStatus); + return true; +} + +bool convertLegacyNanCapabilitiesResponseToHidl( + const legacy_hal::NanCapabilities& legacy_response, + NanCapabilities* hidl_response) { + if (!hidl_response) { + LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: hidl_response is null"; + return false; + } + *hidl_response = {}; + + hidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters; + hidl_response->maxPublishes = legacy_response.max_publishes; + hidl_response->maxSubscribes = legacy_response.max_subscribes; + hidl_response->maxServiceNameLen = legacy_response.max_service_name_len; + hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len; + hidl_response->maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len; + hidl_response->maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len; + hidl_response->maxExtendedServiceSpecificInfoLen = + legacy_response.max_sdea_service_specific_info_len; + hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces; + hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions; + hidl_response->maxAppInfoLen = legacy_response.max_app_info_len; + hidl_response->maxQueuedTransmitFollowupMsgs = legacy_response.max_queued_transmit_followup_msgs; + hidl_response->maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address; + hidl_response->supportedCipherSuites = legacy_response.cipher_suites_supported; + + return true; +} + +bool convertLegacyNanMatchIndToHidl( + const legacy_hal::NanMatchInd& legacy_ind, + NanMatchInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array(legacy_ind.addr); + hidl_ind->serviceSpecificInfo = std::vector(legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector( + legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len); + hidl_ind->matchFilter = std::vector(legacy_ind.sdf_match_filter, + legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len); + hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1; + hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1; + hidl_ind->rssiValue = legacy_ind.rssi_value; + hidl_ind->peerCipherType = (NanCipherSuiteType) legacy_ind.peer_cipher_type; + hidl_ind->peerRequiresSecurityEnabledInNdp = + legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->peerRequiresRanging = + legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE; + hidl_ind->rangingMeasurementInCm = legacy_ind.range_info.range_measurement_cm; + hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type; + + return true; +} + +bool convertLegacyNanFollowupIndToHidl( + const legacy_hal::NanFollowupInd& legacy_ind, + NanFollowupReceivedInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array(legacy_ind.addr); + hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1; + hidl_ind->serviceSpecificInfo = std::vector(legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector( + legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len); + + return true; +} + +bool convertLegacyNanDataPathRequestIndToHidl( + const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.service_instance_id; + hidl_ind->peerDiscMacAddr = hidl_array(legacy_ind.peer_disc_mac_addr); + hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->securityRequired = + legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->appInfo = std::vector(legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len); + + return true; +} + +bool convertLegacyNanDataPathConfirmIndToHidl( + const legacy_hal::NanDataPathConfirmInd& legacy_ind, + NanDataPathConfirmInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT; + hidl_ind->peerNdiMacAddr = hidl_array(legacy_ind.peer_ndi_mac_addr); + hidl_ind->appInfo = std::vector(legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len); + hidl_ind->status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code); + hidl_ind->status.description = ""; // TODO: b/34059183 + + return true; +} + +legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) { + switch (type) { + case RttType::ONE_SIDED: + return legacy_hal::RTT_TYPE_1_SIDED; + case RttType::TWO_SIDED: + return legacy_hal::RTT_TYPE_2_SIDED; + }; + CHECK(false); +} + +RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) { + switch (type) { + case legacy_hal::RTT_TYPE_1_SIDED: + return RttType::ONE_SIDED; + case legacy_hal::RTT_TYPE_2_SIDED: + return RttType::TWO_SIDED; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) { + switch (type) { + case RttPeerType::AP: + return legacy_hal::RTT_PEER_AP; + case RttPeerType::STA: + return legacy_hal::RTT_PEER_STA; + case RttPeerType::P2P_GO: + return legacy_hal::RTT_PEER_P2P_GO; + case RttPeerType::P2P_CLIENT: + return legacy_hal::RTT_PEER_P2P_CLIENT; + case RttPeerType::NAN: + return legacy_hal::RTT_PEER_NAN; + }; + CHECK(false); +} + +legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy( + WifiChannelWidthInMhz type) { + switch (type) { + case WifiChannelWidthInMhz::WIDTH_20: + return legacy_hal::WIFI_CHAN_WIDTH_20; + case WifiChannelWidthInMhz::WIDTH_40: + return legacy_hal::WIFI_CHAN_WIDTH_40; + case WifiChannelWidthInMhz::WIDTH_80: + return legacy_hal::WIFI_CHAN_WIDTH_80; + case WifiChannelWidthInMhz::WIDTH_160: + return legacy_hal::WIFI_CHAN_WIDTH_160; + case WifiChannelWidthInMhz::WIDTH_80P80: + return legacy_hal::WIFI_CHAN_WIDTH_80P80; + case WifiChannelWidthInMhz::WIDTH_5: + return legacy_hal::WIFI_CHAN_WIDTH_5; + case WifiChannelWidthInMhz::WIDTH_10: + return legacy_hal::WIFI_CHAN_WIDTH_10; + case WifiChannelWidthInMhz::WIDTH_INVALID: + return legacy_hal::WIFI_CHAN_WIDTH_INVALID; + }; + CHECK(false); +} + +WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl( + legacy_hal::wifi_channel_width type) { + switch (type) { + case legacy_hal::WIFI_CHAN_WIDTH_20: + return WifiChannelWidthInMhz::WIDTH_20; + case legacy_hal::WIFI_CHAN_WIDTH_40: + return WifiChannelWidthInMhz::WIDTH_40; + case legacy_hal::WIFI_CHAN_WIDTH_80: + return WifiChannelWidthInMhz::WIDTH_80; + case legacy_hal::WIFI_CHAN_WIDTH_160: + return WifiChannelWidthInMhz::WIDTH_160; + case legacy_hal::WIFI_CHAN_WIDTH_80P80: + return WifiChannelWidthInMhz::WIDTH_80P80; + case legacy_hal::WIFI_CHAN_WIDTH_5: + return WifiChannelWidthInMhz::WIDTH_5; + case legacy_hal::WIFI_CHAN_WIDTH_10: + return WifiChannelWidthInMhz::WIDTH_10; + case legacy_hal::WIFI_CHAN_WIDTH_INVALID: + return WifiChannelWidthInMhz::WIDTH_INVALID; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) { + switch (type) { + case RttPreamble::LEGACY: + return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY; + case RttPreamble::HT: + return legacy_hal::WIFI_RTT_PREAMBLE_HT; + case RttPreamble::VHT: + return legacy_hal::WIFI_RTT_PREAMBLE_VHT; + }; + CHECK(false); +} + +RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) { + switch (type) { + case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY: + return RttPreamble::LEGACY; + case legacy_hal::WIFI_RTT_PREAMBLE_HT: + return RttPreamble::HT; + case legacy_hal::WIFI_RTT_PREAMBLE_VHT: + return RttPreamble::VHT; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) { + switch (type) { + case RttBw::BW_5MHZ: + return legacy_hal::WIFI_RTT_BW_5; + case RttBw::BW_10MHZ: + return legacy_hal::WIFI_RTT_BW_10; + case RttBw::BW_20MHZ: + return legacy_hal::WIFI_RTT_BW_20; + case RttBw::BW_40MHZ: + return legacy_hal::WIFI_RTT_BW_40; + case RttBw::BW_80MHZ: + return legacy_hal::WIFI_RTT_BW_80; + case RttBw::BW_160MHZ: + return legacy_hal::WIFI_RTT_BW_160; + }; + CHECK(false); +} + +RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) { + switch (type) { + case legacy_hal::WIFI_RTT_BW_5: + return RttBw::BW_5MHZ; + case legacy_hal::WIFI_RTT_BW_10: + return RttBw::BW_10MHZ; + case legacy_hal::WIFI_RTT_BW_20: + return RttBw::BW_20MHZ; + case legacy_hal::WIFI_RTT_BW_40: + return RttBw::BW_40MHZ; + case legacy_hal::WIFI_RTT_BW_80: + return RttBw::BW_80MHZ; + case legacy_hal::WIFI_RTT_BW_160: + return RttBw::BW_160MHZ; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy( + RttMotionPattern type) { + switch (type) { + case RttMotionPattern::NOT_EXPECTED: + return legacy_hal::WIFI_MOTION_NOT_EXPECTED; + case RttMotionPattern::EXPECTED: + return legacy_hal::WIFI_MOTION_EXPECTED; + case RttMotionPattern::UNKNOWN: + return legacy_hal::WIFI_MOTION_UNKNOWN; + }; + CHECK(false); +} + +WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { + switch (preamble) { + case 0: + return WifiRatePreamble::OFDM; + case 1: + return WifiRatePreamble::CCK; + case 2: + return WifiRatePreamble::HT; + case 3: + return WifiRatePreamble::VHT; + default: + return WifiRatePreamble::RESERVED; + }; + CHECK(false) << "Unknown legacy preamble: " << preamble; +} + +WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) { + switch (nss) { + case 0: + return WifiRateNss::NSS_1x1; + case 1: + return WifiRateNss::NSS_2x2; + case 2: + return WifiRateNss::NSS_3x3; + case 3: + return WifiRateNss::NSS_4x4; + }; + CHECK(false) << "Unknown legacy nss: " << nss; + return {}; +} + +RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) { + switch (status) { + case legacy_hal::RTT_STATUS_SUCCESS: + return RttStatus::SUCCESS; + case legacy_hal::RTT_STATUS_FAILURE: + return RttStatus::FAILURE; + case legacy_hal::RTT_STATUS_FAIL_NO_RSP: + return RttStatus::FAIL_NO_RSP; + case legacy_hal::RTT_STATUS_FAIL_REJECTED: + return RttStatus::FAIL_REJECTED; + case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET: + return RttStatus::FAIL_NOT_SCHEDULED_YET; + case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT: + return RttStatus::FAIL_TM_TIMEOUT; + case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: + return RttStatus::FAIL_AP_ON_DIFF_CHANNEL; + case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY: + return RttStatus::FAIL_NO_CAPABILITY; + case legacy_hal::RTT_STATUS_ABORTED: + return RttStatus::ABORTED; + case legacy_hal::RTT_STATUS_FAIL_INVALID_TS: + return RttStatus::FAIL_INVALID_TS; + case legacy_hal::RTT_STATUS_FAIL_PROTOCOL: + return RttStatus::FAIL_PROTOCOL; + case legacy_hal::RTT_STATUS_FAIL_SCHEDULE: + return RttStatus::FAIL_SCHEDULE; + case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER: + return RttStatus::FAIL_BUSY_TRY_LATER; + case legacy_hal::RTT_STATUS_INVALID_REQ: + return RttStatus::INVALID_REQ; + case legacy_hal::RTT_STATUS_NO_WIFI: + return RttStatus::NO_WIFI; + case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: + return RttStatus::FAIL_FTM_PARAM_OVERRIDE; + }; + CHECK(false) << "Unknown legacy status: " << status; +} + +bool convertHidlWifiChannelInfoToLegacy( + const WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width); + legacy_info->center_freq = hidl_info.centerFreq; + legacy_info->center_freq0 = hidl_info.centerFreq0; + legacy_info->center_freq1 = hidl_info.centerFreq1; + return true; +} + +bool convertLegacyWifiChannelInfoToHidl( + const legacy_hal::wifi_channel_info& legacy_info, + WifiChannelInfo* hidl_info) { + if (!hidl_info) { + return false; + } + *hidl_info = {}; + hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width); + hidl_info->centerFreq = legacy_info.center_freq; + hidl_info->centerFreq0 = legacy_info.center_freq0; + hidl_info->centerFreq1 = legacy_info.center_freq1; + return true; +} + +bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config, + legacy_hal::wifi_rtt_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr)); + memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size()); + legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type); + legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer); + if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel, + &legacy_config->channel)) { + return false; + } + legacy_config->burst_period = hidl_config.burstPeriod; + legacy_config->num_burst = hidl_config.numBurst; + legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst; + legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame; + legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr; + legacy_config->LCI_request = hidl_config.mustRequestLci; + legacy_config->LCR_request = hidl_config.mustRequestLcr; + legacy_config->burst_duration = hidl_config.burstDuration; + legacy_config->preamble = + convertHidlRttPreambleToLegacy(hidl_config.preamble); + legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw); + return true; +} + +bool convertHidlVectorOfRttConfigToLegacy( + const std::vector& hidl_configs, + std::vector* legacy_configs) { + if (!legacy_configs) { + return false; + } + *legacy_configs = {}; + for (const auto& hidl_config : hidl_configs) { + legacy_hal::wifi_rtt_config legacy_config; + if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) { + return false; + } + legacy_configs->push_back(legacy_config); + } + return true; +} + +bool convertHidlRttLciInformationToLegacy( + const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->latitude = hidl_info.latitude; + legacy_info->longitude = hidl_info.longitude; + legacy_info->altitude = hidl_info.altitude; + legacy_info->latitude_unc = hidl_info.latitudeUnc; + legacy_info->longitude_unc = hidl_info.longitudeUnc; + legacy_info->altitude_unc = hidl_info.altitudeUnc; + legacy_info->motion_pattern = + convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern); + legacy_info->floor = hidl_info.floor; + legacy_info->height_above_floor = hidl_info.heightAboveFloor; + legacy_info->height_unc = hidl_info.heightUnc; + return true; +} + +bool convertHidlRttLcrInformationToLegacy( + const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code)); + memcpy(legacy_info->country_code, + hidl_info.countryCode.data(), + hidl_info.countryCode.size()); + if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) { + return false; + } + legacy_info->length = hidl_info.civicInfo.size(); + memcpy(legacy_info->civic_info, + hidl_info.civicInfo.c_str(), + hidl_info.civicInfo.size()); + return true; +} + +bool convertHidlRttResponderToLegacy( + const RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder) { + if (!legacy_responder) { + return false; + } + *legacy_responder = {}; + if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel, + &legacy_responder->channel)) { + return false; + } + legacy_responder->preamble = + convertHidlRttPreambleToLegacy(hidl_responder.preamble); + return true; +} + +bool convertLegacyRttResponderToHidl( + const legacy_hal::wifi_rtt_responder& legacy_responder, + RttResponder* hidl_responder) { + if (!hidl_responder) { + return false; + } + *hidl_responder = {}; + if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel, + &hidl_responder->channel)) { + return false; + } + hidl_responder->preamble = + convertLegacyRttPreambleToHidl(legacy_responder.preamble); + return true; +} + +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + RttCapabilities* hidl_capabilities) { + if (!hidl_capabilities) { + return false; + } + *hidl_capabilities = {}; + hidl_capabilities->rttOneSidedSupported = + legacy_capabilities.rtt_one_sided_supported; + hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported; + hidl_capabilities->lciSupported = legacy_capabilities.lci_support; + hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support; + hidl_capabilities->responderSupported = + legacy_capabilities.responder_supported; + hidl_capabilities->preambleSupport = 0; + for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, + legacy_hal::WIFI_RTT_PREAMBLE_HT, + legacy_hal::WIFI_RTT_PREAMBLE_VHT}) { + if (legacy_capabilities.preamble_support & flag) { + hidl_capabilities->preambleSupport |= + static_cast::type>( + convertLegacyRttPreambleToHidl(flag)); + } + } + hidl_capabilities->bwSupport = 0; + for (const auto flag : {legacy_hal::WIFI_RTT_BW_5, + legacy_hal::WIFI_RTT_BW_10, + legacy_hal::WIFI_RTT_BW_20, + legacy_hal::WIFI_RTT_BW_40, + legacy_hal::WIFI_RTT_BW_80, + legacy_hal::WIFI_RTT_BW_160}) { + if (legacy_capabilities.bw_support & flag) { + hidl_capabilities->bwSupport |= + static_cast::type>( + convertLegacyRttBwToHidl(flag)); + } + } + hidl_capabilities->mcVersion = legacy_capabilities.mc_version; + return true; +} + +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + WifiRateInfo* hidl_rate) { + if (!hidl_rate) { + return false; + } + *hidl_rate = {}; + hidl_rate->preamble = + convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble); + hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss); + hidl_rate->bw = convertLegacyWifiChannelWidthToHidl( + static_cast(legacy_rate.bw)); + hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx; + hidl_rate->bitRateInKbps = legacy_rate.bitrate; + return true; +} + +bool convertLegacyRttResultToHidl( + const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) { + if (!hidl_result) { + return false; + } + *hidl_result = {}; + CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size()); + memcpy( + hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr)); + hidl_result->burstNum = legacy_result.burst_num; + hidl_result->measurementNumber = legacy_result.measurement_number; + hidl_result->successNumber = legacy_result.success_number; + hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer; + hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status); + hidl_result->retryAfterDuration = legacy_result.retry_after_duration; + hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type); + hidl_result->rssi = legacy_result.rssi; + hidl_result->rssiSpread = legacy_result.rssi_spread; + if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate, + &hidl_result->txRate)) { + return false; + } + if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate, + &hidl_result->rxRate)) { + return false; + } + hidl_result->rtt = legacy_result.rtt; + hidl_result->rttSd = legacy_result.rtt_sd; + hidl_result->rttSpread = legacy_result.rtt_spread; + hidl_result->distanceInMm = legacy_result.distance_mm; + hidl_result->distanceSdInMm = legacy_result.distance_sd_mm; + hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm; + hidl_result->timeStampInUs = legacy_result.ts; + hidl_result->burstDurationInMs = legacy_result.burst_duration; + hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num; + if (legacy_result.LCI && !convertLegacyIeToHidl(*legacy_result.LCI, + &hidl_result->lci)) { + return false; + } + if (legacy_result.LCR && !convertLegacyIeToHidl(*legacy_result.LCR, + &hidl_result->lcr)) { + return false; + } + return true; +} + +bool convertLegacyVectorOfRttResultToHidl( + const std::vector& legacy_results, + std::vector* hidl_results) { + if (!hidl_results) { + return false; + } + *hidl_results = {}; + for (const auto legacy_result : legacy_results) { + RttResult hidl_result; + if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) { + return false; + } + hidl_results->push_back(hidl_result); + } + return true; +} +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/hidl_struct_util.h b/wifi/1.1/default/hidl_struct_util.h new file mode 100644 index 000000000..a04f6363d --- /dev/null +++ b/wifi/1.1/default/hidl_struct_util.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef HIDL_STRUCT_UTIL_H_ +#define HIDL_STRUCT_UTIL_H_ + +#include + +#include + +#include "wifi_legacy_hal.h" + +/** + * This file contains a bunch of functions to convert structs from the legacy + * HAL to HIDL and vice versa. + * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test + * suite. + */ +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_struct_util { +using namespace android::hardware::wifi::V1_0; + +// Chip conversion methods. +bool convertLegacyFeaturesToHidlChipCapabilities( + uint32_t legacy_logger_feature_set, uint32_t* hidl_caps); +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status); +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector& legacy_status_vec, + std::vector* hidl_status_vec); +bool convertLegacyWakeReasonStatsToHidl( + const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats); + +// STA iface conversion methods. +bool convertLegacyFeaturesToHidlStaCapabilities( + uint32_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps); +bool convertLegacyApfCapabilitiesToHidl( + const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps); +bool convertLegacyGscanCapabilitiesToHidl( + const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps); +legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band); +bool convertHidlGscanParamsToLegacy( + const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params); +// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11 +// Information Elements (IEs) +bool convertLegacyGscanResultToHidl( + const legacy_hal::wifi_scan_result& legacy_scan_result, + bool has_ie_data, + StaScanResult* hidl_scan_result); +// |cached_results| is assumed to not include IEs. +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector& + legacy_cached_scan_results, + std::vector* hidl_scan_datas); +bool convertLegacyLinkLayerStatsToHidl( + const legacy_hal::LinkLayerStats& legacy_stats, + StaLinkLayerStats* hidl_stats); +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps); +bool convertHidlRoamingConfigToLegacy( + const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config); +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy( + StaRoamingState state); +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates); +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates); + +// NAN iface conversion methods. +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, + WifiNanStatus* wifiNanStatus); +bool convertHidlNanEnableRequestToLegacy( + const NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequestToLegacy( + const NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanPublishRequestToLegacy( + const NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request); +bool convertHidlNanSubscribeRequestToLegacy( + const NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request); +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request); +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponseToLegacy( + const NanRespondToDataPathIndicationRequest& hidl_response, + legacy_hal::NanDataPathIndicationResponse* legacy_response); +bool convertLegacyNanResponseHeaderToHidl( + const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus); +bool convertLegacyNanCapabilitiesResponseToHidl( + const legacy_hal::NanCapabilities& legacy_response, + NanCapabilities* hidl_response); +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + NanMatchInd* hidl_ind); +bool convertLegacyNanFollowupIndToHidl( + const legacy_hal::NanFollowupInd& legacy_ind, NanFollowupReceivedInd* hidl_ind); +bool convertLegacyNanDataPathRequestIndToHidl( + const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind); +bool convertLegacyNanDataPathConfirmIndToHidl( + const legacy_hal::NanDataPathConfirmInd& legacy_ind, + NanDataPathConfirmInd* hidl_ind); + +// RTT controller conversion methods. +bool convertHidlVectorOfRttConfigToLegacy( + const std::vector& hidl_configs, + std::vector* legacy_configs); +bool convertHidlRttLciInformationToLegacy( + const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info); +bool convertHidlRttLcrInformationToLegacy( + const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info); +bool convertHidlRttResponderToLegacy( + const RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder); +bool convertHidlWifiChannelInfoToLegacy( + const WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info); +bool convertLegacyRttResponderToHidl( + const legacy_hal::wifi_rtt_responder& legacy_responder, + RttResponder* hidl_responder); +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + RttCapabilities* hidl_capabilities); +bool convertLegacyVectorOfRttResultToHidl( + const std::vector& legacy_results, + std::vector* hidl_results); +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // HIDL_STRUCT_UTIL_H_ diff --git a/wifi/1.1/default/hidl_sync_util.cpp b/wifi/1.1/default/hidl_sync_util.cpp new file mode 100644 index 000000000..ba18e344a --- /dev/null +++ b/wifi/1.1/default/hidl_sync_util.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 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 "hidl_sync_util.h" + +namespace { +std::recursive_mutex g_mutex; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_sync_util { + +std::unique_lock acquireGlobalLock() { + return std::unique_lock{g_mutex}; +} + +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/hidl_sync_util.h b/wifi/1.1/default/hidl_sync_util.h new file mode 100644 index 000000000..0e882df50 --- /dev/null +++ b/wifi/1.1/default/hidl_sync_util.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef HIDL_SYNC_UTIL_H_ +#define HIDL_SYNC_UTIL_H_ + +#include + +// Utility that provides a global lock to synchronize access between +// the HIDL thread and the legacy HAL's event loop. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace hidl_sync_util { +std::unique_lock acquireGlobalLock(); +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_SYNC_UTIL_H_ diff --git a/wifi/1.1/default/service.cpp b/wifi/1.1/default/service.cpp new file mode 100644 index 000000000..b3fcd50e5 --- /dev/null +++ b/wifi/1.1/default/service.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 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 +#include +#include +#include + +#include "wifi.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; + +int main(int /*argc*/, char** argv) { + android::base::InitLogging(argv, + android::base::LogdLogger(android::base::SYSTEM)); + LOG(INFO) << "Wifi Hal is starting up..."; + + configureRpcThreadpool(1, true /* callerWillJoin */); + + // Setup hwbinder service + android::sp service = + new android::hardware::wifi::V1_1::implementation::Wifi(); + CHECK_EQ(service->registerAsService(), android::NO_ERROR) + << "Failed to register wifi HAL"; + + joinRpcThreadpool(); + + LOG(INFO) << "Wifi Hal is terminating..."; + return 0; +} diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp new file mode 100644 index 000000000..4ed1f555e --- /dev/null +++ b/wifi/1.1/default/wifi.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "wifi.h" +#include "wifi_status_util.h" + +namespace { +// Chip ID to use for the only supported chip. +static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +Wifi::Wifi() + : legacy_hal_(new legacy_hal::WifiLegacyHal()), + mode_controller_(new mode_controller::WifiModeController()), + run_state_(RunState::STOPPED) {} + +bool Wifi::isValid() { + // This object is always valid. + return true; +} + +Return Wifi::registerEventCallback( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal, + hidl_status_cb, + event_callback); +} + +Return Wifi::isStarted() { + return run_state_ != RunState::STOPPED; +} + +Return Wifi::start(start_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_UNKNOWN, + &Wifi::startInternal, + hidl_status_cb); +} + +Return Wifi::stop(stop_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb); +} + +Return Wifi::getChipIds(getChipIds_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_UNKNOWN, + &Wifi::getChipIdsInternal, + hidl_status_cb); +} + +Return Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_UNKNOWN, + &Wifi::getChipInternal, + hidl_status_cb, + chip_id); +} + +WifiStatus Wifi::registerEventCallbackInternal( + const sp& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::startInternal() { + if (run_state_ == RunState::STARTED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, + "HAL is stopping"); + } + WifiStatus wifi_status = initializeLegacyHal(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Create the chip instance once the HAL is started. + chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_); + run_state_ = RunState::STARTED; + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStart().isOk()) { + LOG(ERROR) << "Failed to invoke onStart callback"; + }; + } + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + } + LOG(INFO) << "Wifi HAL started"; + return wifi_status; +} + +WifiStatus Wifi::stopInternal() { + if (run_state_ == RunState::STOPPED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, + "HAL is stopping"); + } + WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStop().isOk()) { + LOG(ERROR) << "Failed to invoke onStop callback"; + }; + } + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + } + // Clear the chip object and its child objects since the HAL is now + // stopped. + if (chip_.get()) { + chip_->invalidate(); + chip_.clear(); + } + LOG(INFO) << "Wifi HAL stopped"; + return wifi_status; +} + +std::pair> Wifi::getChipIdsInternal() { + std::vector chip_ids; + if (chip_.get()) { + chip_ids.emplace_back(kChipId); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)}; +} + +std::pair> Wifi::getChipInternal(ChipId chip_id) { + if (!chip_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr}; + } + if (chip_id != kChipId) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_}; +} + +WifiStatus Wifi::initializeLegacyHal() { + legacy_hal::wifi_error legacy_status = legacy_hal_->initialize(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to initialize legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() { + run_state_ = RunState::STOPPING; + const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; }; + legacy_hal::wifi_error legacy_status = + legacy_hal_->stop(on_complete_callback_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + if (!mode_controller_->deinitialize()) { + LOG(ERROR) << "Failed to deinitialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h new file mode 100644 index 000000000..1ade2d8b9 --- /dev/null +++ b/wifi/1.1/default/wifi.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_H_ +#define WIFI_H_ + +#include + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_chip.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * Root HIDL interface object used to control the Wifi HAL. + */ +class Wifi : public V1_1::IWifi { + public: + Wifi(); + + bool isValid(); + + // HIDL methods exposed. + Return registerEventCallback( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return isStarted() override; + Return start(start_cb hidl_status_cb) override; + Return stop(stop_cb hidl_status_cb) override; + Return getChipIds(getChipIds_cb hidl_status_cb) override; + Return getChip(ChipId chip_id, getChip_cb hidl_status_cb) override; + + private: + enum class RunState { STOPPED, STARTED, STOPPING }; + + // Corresponding worker functions for the HIDL methods. + WifiStatus registerEventCallbackInternal( + const sp& event_callback); + WifiStatus startInternal(); + WifiStatus stopInternal(); + std::pair> getChipIdsInternal(); + std::pair> getChipInternal(ChipId chip_id); + + WifiStatus initializeLegacyHal(); + WifiStatus stopLegacyHalAndDeinitializeModeController(); + + // Instance is created in this root level |IWifi| HIDL interface object + // and shared with all the child HIDL interface objects. + std::shared_ptr legacy_hal_; + std::shared_ptr mode_controller_; + RunState run_state_; + sp chip_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(Wifi); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_H_ diff --git a/wifi/1.1/default/wifi_ap_iface.cpp b/wifi/1.1/default/wifi_ap_iface.cpp new file mode 100644 index 000000000..150a6cc06 --- /dev/null +++ b/wifi/1.1/default/wifi_ap_iface.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_ap_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiApIface::WifiApIface( + const std::string& ifname, + const std::weak_ptr legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiApIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiApIface::isValid() { + return is_valid_; +} + +Return WifiApIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getNameInternal, + hidl_status_cb); +} + +Return WifiApIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getTypeInternal, + hidl_status_cb); +} + +Return WifiApIface::setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setCountryCodeInternal, + hidl_status_cb, + code); +} + +Return WifiApIface::getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getValidFrequenciesForBandInternal, + hidl_status_cb, + band); +} + +std::pair WifiApIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiApIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP}; +} + +WifiStatus WifiApIface::setCountryCodeInternal( + const std::array& code) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setCountryCode(code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> +WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector valid_frequencies; + std::tie(legacy_status, valid_frequencies) = + legacy_hal_.lock()->getValidFrequenciesForBand( + hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_ap_iface.h b/wifi/1.1/default/wifi_ap_iface.h new file mode 100644 index 000000000..608fe6b5a --- /dev/null +++ b/wifi/1.1/default/wifi_ap_iface.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_AP_IFACE_H_ +#define WIFI_AP_IFACE_H_ + +#include +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a AP Iface instance. + */ +class WifiApIface : public V1_0::IWifiApIface { + public: + WifiApIface(const std::string& ifname, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) override; + Return getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus setCountryCodeInternal(const std::array& code); + std::pair> + getValidFrequenciesForBandInternal(WifiBand band); + + std::string ifname_; + std::weak_ptr legacy_hal_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiApIface); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_AP_IFACE_H_ diff --git a/wifi/1.1/default/wifi_chip.cpp b/wifi/1.1/default/wifi_chip.cpp new file mode 100644 index 000000000..87985c067 --- /dev/null +++ b/wifi/1.1/default/wifi_chip.cpp @@ -0,0 +1,904 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_chip.h" +#include "wifi_feature_flags.h" +#include "wifi_status_util.h" + +namespace { +using android::sp; +using android::hardware::hidl_vec; +using android::hardware::hidl_string; +using android::hardware::wifi::V1_0::ChipModeId; +using android::hardware::wifi::V1_0::IWifiChip; +using android::hardware::wifi::V1_0::IfaceType; + +constexpr ChipModeId kStaChipModeId = 0; +constexpr ChipModeId kApChipModeId = 1; +constexpr ChipModeId kInvalidModeId = UINT32_MAX; + +template +void invalidateAndClear(sp& iface) { + if (iface.get()) { + iface->invalidate(); + iface.clear(); + } +} +} // namepsace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiChip::WifiChip( + ChipId chip_id, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller) + : chip_id_(chip_id), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + is_valid_(true), + current_mode_id_(kInvalidModeId), + debug_ring_buffer_cb_registered_(false) {} + +void WifiChip::invalidate() { + invalidateAndRemoveAllIfaces(); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiChip::isValid() { + return is_valid_; +} + +std::set> WifiChip::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return WifiChip::getId(getId_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getIdInternal, + hidl_status_cb); +} + +Return WifiChip::registerEventCallback( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal, + hidl_status_cb, + event_callback); +} + +Return WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal, + hidl_status_cb); +} + +Return WifiChip::configureChip(ChipModeId mode_id, + configureChip_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::configureChipInternal, + hidl_status_cb, + mode_id); +} + +Return WifiChip::getMode(getMode_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getModeInternal, + hidl_status_cb); +} + +Return WifiChip::requestChipDebugInfo( + requestChipDebugInfo_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestChipDebugInfoInternal, + hidl_status_cb); +} + +Return WifiChip::requestDriverDebugDump( + requestDriverDebugDump_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestDriverDebugDumpInternal, + hidl_status_cb); +} + +Return WifiChip::requestFirmwareDebugDump( + requestFirmwareDebugDump_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestFirmwareDebugDumpInternal, + hidl_status_cb); +} + +Return WifiChip::createApIface(createApIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createApIfaceInternal, + hidl_status_cb); +} + +Return WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceNamesInternal, + hidl_status_cb); +} + +Return WifiChip::getApIface(const hidl_string& ifname, + getApIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::removeApIface(const hidl_string& ifname, + removeApIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeApIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::createNanIface(createNanIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createNanIfaceInternal, + hidl_status_cb); +} + +Return WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceNamesInternal, + hidl_status_cb); +} + +Return WifiChip::getNanIface(const hidl_string& ifname, + getNanIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeNanIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createP2pIfaceInternal, + hidl_status_cb); +} + +Return WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceNamesInternal, + hidl_status_cb); +} + +Return WifiChip::getP2pIface(const hidl_string& ifname, + getP2pIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeP2pIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::createStaIface(createStaIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createStaIfaceInternal, + hidl_status_cb); +} + +Return WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceNamesInternal, + hidl_status_cb); +} + +Return WifiChip::getStaIface(const hidl_string& ifname, + getStaIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeStaIfaceInternal, + hidl_status_cb, + ifname); +} + +Return WifiChip::createRttController( + const sp& bound_iface, createRttController_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal, + hidl_status_cb, + bound_iface); +} + +Return WifiChip::getDebugRingBuffersStatus( + getDebugRingBuffersStatus_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugRingBuffersStatusInternal, + hidl_status_cb); +} + +Return WifiChip::startLoggingToDebugRingBuffer( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, + uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::startLoggingToDebugRingBufferInternal, + hidl_status_cb, + ring_name, + verbose_level, + max_interval_in_sec, + min_data_size_in_bytes); +} + +Return WifiChip::forceDumpToDebugRingBuffer( + const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::forceDumpToDebugRingBufferInternal, + hidl_status_cb, + ring_name); +} + +Return WifiChip::stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::stopLoggingToDebugRingBufferInternal, + hidl_status_cb); +} + +Return WifiChip::getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugHostWakeReasonStatsInternal, + hidl_status_cb); +} + +Return WifiChip::enableDebugErrorAlerts( + bool enable, enableDebugErrorAlerts_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::enableDebugErrorAlertsInternal, + hidl_status_cb, + enable); +} + +Return WifiChip::setTxPowerLimit( + int32_t powerInDbm, setTxPowerLimit_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setTxPowerLimitInternal, + hidl_status_cb, + powerInDbm); +} + +Return WifiChip::resetTxPowerLimit( + resetTxPowerLimit_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::resetTxPowerLimitInternal, + hidl_status_cb); +} + +void WifiChip::invalidateAndRemoveAllIfaces() { + invalidateAndClear(ap_iface_); + invalidateAndClear(nan_iface_); + invalidateAndClear(p2p_iface_); + invalidateAndClear(sta_iface_); + // Since all the ifaces are invalid now, all RTT controller objects + // using those ifaces also need to be invalidated. + for (const auto& rtt : rtt_controllers_) { + rtt->invalidate(); + } + rtt_controllers_.clear(); +} + +std::pair WifiChip::getIdInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_}; +} + +WifiStatus WifiChip::registerEventCallbackInternal( + const sp& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair WifiChip::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + uint32_t legacy_logger_feature_set; + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities( + legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair> +WifiChip::getAvailableModesInternal() { + // The chip combination supported for current devices is fixed for now with + // 2 separate modes of operation: + // Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN iface operations + // concurrently [NAN conditional on wifiHidlFeatureAware] + // Mode 2 (AP mode): Will support 1 AP iface operations. + // TODO (b/32997844): Read this from some device specific flags in the + // makefile. + // STA mode iface combinations. + const IWifiChip::ChipIfaceCombinationLimit + sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1}; + IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2; + if (WifiFeatureFlags::wifiHidlFeatureAware) { + sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN}, + 1}; + } else { + sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, + 1}; + } + const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = { + {sta_chip_iface_combination_limit_1, sta_chip_iface_combination_limit_2}}; + const IWifiChip::ChipMode sta_chip_mode = {kStaChipModeId, + {sta_chip_iface_combination}}; + // AP mode iface combinations. + const IWifiChip::ChipIfaceCombinationLimit ap_chip_iface_combination_limit = { + {IfaceType::AP}, 1}; + const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = { + {ap_chip_iface_combination_limit}}; + const IWifiChip::ChipMode ap_chip_mode = {kApChipModeId, + {ap_chip_iface_combination}}; + return {createWifiStatus(WifiStatusCode::SUCCESS), + {sta_chip_mode, ap_chip_mode}}; +} + +WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) { + if (mode_id != kStaChipModeId && mode_id != kApChipModeId) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + if (mode_id == current_mode_id_) { + LOG(DEBUG) << "Already in the specified mode " << mode_id; + return createWifiStatus(WifiStatusCode::SUCCESS); + } + WifiStatus status = handleChipConfiguration(mode_id); + if (status.code != WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigureFailure(status).isOk()) { + LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback"; + } + } + return status; + } + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigured(mode_id).isOk()) { + LOG(ERROR) << "Failed to invoke onChipReconfigured callback"; + } + } + current_mode_id_ = mode_id; + return status; +} + +std::pair WifiChip::getModeInternal() { + if (current_mode_id_ == kInvalidModeId) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), + current_mode_id_}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; +} + +std::pair +WifiChip::requestChipDebugInfoInternal() { + IWifiChip::ChipDebugInfo result; + legacy_hal::wifi_error legacy_status; + std::string driver_desc; + std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver version: " + << legacyErrorToString(legacy_status); + WifiStatus status = createWifiStatusFromLegacyError( + legacy_status, "failed to get driver version"); + return {status, result}; + } + result.driverDescription = driver_desc.c_str(); + + std::string firmware_desc; + std::tie(legacy_status, firmware_desc) = + legacy_hal_.lock()->getFirmwareVersion(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware version: " + << legacyErrorToString(legacy_status); + WifiStatus status = createWifiStatusFromLegacyError( + legacy_status, "failed to get firmware version"); + return {status, result}; + } + result.firmwareDescription = firmware_desc.c_str(); + + return {createWifiStatus(WifiStatusCode::SUCCESS), result}; +} + +std::pair> +WifiChip::requestDriverDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector driver_dump; + std::tie(legacy_status, driver_dump) = + legacy_hal_.lock()->requestDriverMemoryDump(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver debug dump: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), + std::vector()}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump}; +} + +std::pair> +WifiChip::requestFirmwareDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector firmware_dump; + std::tie(legacy_status, firmware_dump) = + legacy_hal_.lock()->requestFirmwareMemoryDump(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware debug dump: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump}; +} + +std::pair> WifiChip::createApIfaceInternal() { + if (current_mode_id_ != kApChipModeId || ap_iface_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = legacy_hal_.lock()->getApIfaceName(); + ap_iface_ = new WifiApIface(ifname, legacy_hal_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_}; +} + +std::pair> +WifiChip::getApIfaceNamesInternal() { + if (!ap_iface_.get()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + {legacy_hal_.lock()->getApIfaceName()}}; +} + +std::pair> WifiChip::getApIfaceInternal( + const std::string& ifname) { + if (!ap_iface_.get() || (ifname != legacy_hal_.lock()->getApIfaceName())) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_}; +} + +WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { + if (!ap_iface_.get() || (ifname != legacy_hal_.lock()->getApIfaceName())) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(ap_iface_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createNanIfaceInternal() { + // Only 1 of NAN or P2P iface can be active at a time. + if (WifiFeatureFlags::wifiHidlFeatureAware) { + if (current_mode_id_ != kStaChipModeId || nan_iface_.get() || + p2p_iface_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = legacy_hal_.lock()->getNanIfaceName(); + nan_iface_ = new WifiNanIface(ifname, legacy_hal_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_}; + } else { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } +} + +std::pair> +WifiChip::getNanIfaceNamesInternal() { + if (!nan_iface_.get()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + {legacy_hal_.lock()->getNanIfaceName()}}; +} + +std::pair> WifiChip::getNanIfaceInternal( + const std::string& ifname) { + if (!nan_iface_.get() || (ifname != legacy_hal_.lock()->getNanIfaceName())) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_}; +} + +WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) { + if (!nan_iface_.get() || (ifname != legacy_hal_.lock()->getNanIfaceName())) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(nan_iface_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createP2pIfaceInternal() { + // Only 1 of NAN or P2P iface can be active at a time. + if (current_mode_id_ != kStaChipModeId || p2p_iface_.get() || + nan_iface_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = legacy_hal_.lock()->getP2pIfaceName(); + p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_}; +} + +std::pair> +WifiChip::getP2pIfaceNamesInternal() { + if (!p2p_iface_.get()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + {legacy_hal_.lock()->getP2pIfaceName()}}; +} + +std::pair> WifiChip::getP2pIfaceInternal( + const std::string& ifname) { + if (!p2p_iface_.get() || (ifname != legacy_hal_.lock()->getP2pIfaceName())) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_}; +} + +WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { + if (!p2p_iface_.get() || (ifname != legacy_hal_.lock()->getP2pIfaceName())) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(p2p_iface_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createStaIfaceInternal() { + if (current_mode_id_ != kStaChipModeId || sta_iface_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = legacy_hal_.lock()->getStaIfaceName(); + sta_iface_ = new WifiStaIface(ifname, legacy_hal_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_}; +} + +std::pair> +WifiChip::getStaIfaceNamesInternal() { + if (!sta_iface_.get()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + {legacy_hal_.lock()->getStaIfaceName()}}; +} + +std::pair> WifiChip::getStaIfaceInternal( + const std::string& ifname) { + if (!sta_iface_.get() || (ifname != legacy_hal_.lock()->getStaIfaceName())) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_}; +} + +WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { + if (!sta_iface_.get() || (ifname != legacy_hal_.lock()->getStaIfaceName())) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(sta_iface_); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> +WifiChip::createRttControllerInternal(const sp& bound_iface) { + sp rtt = new WifiRttController(bound_iface, legacy_hal_); + rtt_controllers_.emplace_back(rtt); + return {createWifiStatus(WifiStatusCode::SUCCESS), rtt}; +} + +std::pair> +WifiChip::getDebugRingBuffersStatusInternal() { + legacy_hal::wifi_error legacy_status; + std::vector + legacy_ring_buffer_status_vec; + std::tie(legacy_status, legacy_ring_buffer_status_vec) = + legacy_hal_.lock()->getRingBuffersStatus(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_ring_buffer_status_vec; + if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl( + legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + hidl_ring_buffer_status_vec}; +} + +WifiStatus WifiChip::startLoggingToDebugRingBufferInternal( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, + uint32_t min_data_size_in_bytes) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRingBufferLogging( + ring_name, + static_cast< + std::underlying_type::type>( + verbose_level), + max_interval_in_sec, + min_data_size_in_bytes); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::forceDumpToDebugRingBufferInternal( + const hidl_string& ring_name) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->getRingBufferData(ring_name); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deregisterRingBufferCallbackHandler(); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiChip::getDebugHostWakeReasonStatsInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::WakeReasonStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getWakeReasonStats(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + WifiDebugHostWakeReasonStats hidl_stats; + if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats, + &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { + legacy_hal::wifi_error legacy_status; + if (enable) { + android::wp weak_ptr_this(this); + const auto& on_alert_callback = [weak_ptr_this]( + int32_t error_code, std::vector debug_data) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) { + LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback"; + } + } + }; + legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler( + on_alert_callback); + } else { + legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(); + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setTxPowerLimitInternal(int32_t /* powerInDbm */) { + // TODO(b/62437848): Implement this method once we are ready with the + // header changes in legacy HAL. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiChip::resetTxPowerLimitInternal() { + // TODO(b/62437848): Implement this method once we are ready with the + // header changes in legacy HAL. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id) { + // If the chip is already configured in a different mode, stop + // the legacy HAL and then start it after firmware mode change. + // Currently the underlying implementation has a deadlock issue. + // We should return ERROR_NOT_SUPPORTED if chip is already configured in + // a different mode. + if (current_mode_id_ != kInvalidModeId) { + // TODO(b/37446050): Fix the deadlock. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); + } + bool success; + if (mode_id == kStaChipModeId) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); + } else { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP); + } + if (!success) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to start legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::registerDebugRingBufferCallback() { + if (debug_ring_buffer_cb_registered_) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } + + android::wp weak_ptr_this(this); + const auto& on_ring_buffer_data_callback = [weak_ptr_this]( + const std::string& /* name */, + const std::vector& data, + const legacy_hal::wifi_ring_buffer_status& status) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiDebugRingBufferStatus hidl_status; + if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl( + status, &hidl_status)) { + LOG(ERROR) << "Error converting ring buffer status"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onDebugRingBufferDataAvailable(hidl_status, data).isOk()) { + LOG(ERROR) << "Failed to invoke onDebugRingBufferDataAvailable" + << " callback on: " << toString(callback); + + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->registerRingBufferCallbackHandler( + on_ring_buffer_data_callback); + + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = true; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_chip.h b/wifi/1.1/default/wifi_chip.h new file mode 100644 index 000000000..b7dde5013 --- /dev/null +++ b/wifi/1.1/default/wifi_chip.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_CHIP_H_ +#define WIFI_CHIP_H_ + +#include + +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_ap_iface.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" +#include "wifi_nan_iface.h" +#include "wifi_p2p_iface.h" +#include "wifi_rtt_controller.h" +#include "wifi_sta_iface.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a Wifi HAL chip instance. + * Since there is only a single chip instance used today, there is no + * identifying handle information stored here. + */ +class WifiChip : public V1_1::IWifiChip { + public: + WifiChip( + ChipId chip_id, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller); + // HIDL does not provide a built-in mechanism to let the server invalidate + // a HIDL interface object after creation. If any client process holds onto + // a reference to the object in their context, any method calls on that + // reference will continue to be directed to the server. + // + // However Wifi HAL needs to control the lifetime of these objects. So, add + // a public |invalidate| method to |WifiChip| and it's child objects. This + // will be used to mark an object invalid when either: + // a) Wifi HAL is stopped, or + // b) Wifi Chip is reconfigured. + // + // All HIDL method implementations should check if the object is still marked + // valid before processing them. + void invalidate(); + bool isValid(); + std::set> getEventCallbacks(); + + // HIDL methods exposed. + Return getId(getId_cb hidl_status_cb) override; + Return registerEventCallback( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return getAvailableModes(getAvailableModes_cb hidl_status_cb) override; + Return configureChip(ChipModeId mode_id, + configureChip_cb hidl_status_cb) override; + Return getMode(getMode_cb hidl_status_cb) override; + Return requestChipDebugInfo( + requestChipDebugInfo_cb hidl_status_cb) override; + Return requestDriverDebugDump( + requestDriverDebugDump_cb hidl_status_cb) override; + Return requestFirmwareDebugDump( + requestFirmwareDebugDump_cb hidl_status_cb) override; + Return createApIface(createApIface_cb hidl_status_cb) override; + Return getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; + Return getApIface(const hidl_string& ifname, + getApIface_cb hidl_status_cb) override; + Return removeApIface(const hidl_string& ifname, + removeApIface_cb hidl_status_cb) override; + Return createNanIface(createNanIface_cb hidl_status_cb) override; + Return getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; + Return getNanIface(const hidl_string& ifname, + getNanIface_cb hidl_status_cb) override; + Return removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) override; + Return createP2pIface(createP2pIface_cb hidl_status_cb) override; + Return getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override; + Return getP2pIface(const hidl_string& ifname, + getP2pIface_cb hidl_status_cb) override; + Return removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) override; + Return createStaIface(createStaIface_cb hidl_status_cb) override; + Return getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override; + Return getStaIface(const hidl_string& ifname, + getStaIface_cb hidl_status_cb) override; + Return removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) override; + Return createRttController( + const sp& bound_iface, + createRttController_cb hidl_status_cb) override; + Return getDebugRingBuffersStatus( + getDebugRingBuffersStatus_cb hidl_status_cb) override; + Return startLoggingToDebugRingBuffer( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, + uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return forceDumpToDebugRingBuffer( + const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) override; + Return stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) override; + Return enableDebugErrorAlerts( + bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override; + Return setTxPowerLimit( + int32_t powerInDbm, setTxPowerLimit_cb hidl_status_cb) override; + Return resetTxPowerLimit(resetTxPowerLimit_cb hidl_status_cb) override; + + private: + void invalidateAndRemoveAllIfaces(); + + // Corresponding worker functions for the HIDL methods. + std::pair getIdInternal(); + WifiStatus registerEventCallbackInternal( + const sp& event_callback); + std::pair getCapabilitiesInternal(); + std::pair> getAvailableModesInternal(); + WifiStatus configureChipInternal(ChipModeId mode_id); + std::pair getModeInternal(); + std::pair + requestChipDebugInfoInternal(); + std::pair> requestDriverDebugDumpInternal(); + std::pair> + requestFirmwareDebugDumpInternal(); + std::pair> createApIfaceInternal(); + std::pair> getApIfaceNamesInternal(); + std::pair> getApIfaceInternal( + const std::string& ifname); + WifiStatus removeApIfaceInternal(const std::string& ifname); + std::pair> createNanIfaceInternal(); + std::pair> getNanIfaceNamesInternal(); + std::pair> getNanIfaceInternal( + const std::string& ifname); + WifiStatus removeNanIfaceInternal(const std::string& ifname); + std::pair> createP2pIfaceInternal(); + std::pair> getP2pIfaceNamesInternal(); + std::pair> getP2pIfaceInternal( + const std::string& ifname); + WifiStatus removeP2pIfaceInternal(const std::string& ifname); + std::pair> createStaIfaceInternal(); + std::pair> getStaIfaceNamesInternal(); + std::pair> getStaIfaceInternal( + const std::string& ifname); + WifiStatus removeStaIfaceInternal(const std::string& ifname); + std::pair> createRttControllerInternal( + const sp& bound_iface); + std::pair> + getDebugRingBuffersStatusInternal(); + WifiStatus startLoggingToDebugRingBufferInternal( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, + uint32_t min_data_size_in_bytes); + WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name); + WifiStatus stopLoggingToDebugRingBufferInternal(); + std::pair + getDebugHostWakeReasonStatsInternal(); + WifiStatus enableDebugErrorAlertsInternal(bool enable); + WifiStatus setTxPowerLimitInternal(int32_t powerInDbm); + WifiStatus resetTxPowerLimitInternal(); + + WifiStatus handleChipConfiguration(ChipModeId mode_id); + WifiStatus registerDebugRingBufferCallback(); + + ChipId chip_id_; + std::weak_ptr legacy_hal_; + std::weak_ptr mode_controller_; + sp ap_iface_; + sp nan_iface_; + sp p2p_iface_; + sp sta_iface_; + std::vector> rtt_controllers_; + bool is_valid_; + uint32_t current_mode_id_; + // The legacy ring buffer callback API has only a global callback + // registration mechanism. Use this to check if we have already + // registered a callback. + bool debug_ring_buffer_cb_registered_; + hidl_callback_util::HidlCallbackHandler + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiChip); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_CHIP_H_ diff --git a/wifi/1.1/default/wifi_feature_flags.h b/wifi/1.1/default/wifi_feature_flags.h new file mode 100644 index 000000000..5939ffbef --- /dev/null +++ b/wifi/1.1/default/wifi_feature_flags.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_FEATURE_FLAGS_H_ +#define WIFI_FEATURE_FLAGS_H_ + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { + +class WifiFeatureFlags { + public: +#ifdef WIFI_HIDL_FEATURE_AWARE + static const bool wifiHidlFeatureAware = true; +#else + static const bool wifiHidlFeatureAware = false; +#endif // WIFI_HIDL_FEATURE_AWARE +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_FEATURE_FLAGS_H_ diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp new file mode 100644 index 000000000..c1e1cd3a4 --- /dev/null +++ b/wifi/1.1/default/wifi_legacy_hal.cpp @@ -0,0 +1,1322 @@ +/* + * Copyright (C) 2016 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 + +#include +#include + +#include "hidl_sync_util.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +// Constants ported over from the legacy HAL calling code +// (com_android_server_wifi_WifiNative.cpp). This will all be thrown +// away when this shim layer is replaced by the real vendor +// implementation. +static constexpr uint32_t kMaxVersionStringLength = 256; +static constexpr uint32_t kMaxCachedGscanResults = 64; +static constexpr uint32_t kMaxGscanFrequenciesForBand = 64; +static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128; +static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32; +static constexpr uint32_t kMaxRingBuffers = 10; + +// Helper function to create a non-const char* for legacy Hal API's. +std::vector makeCharVec(const std::string& str) { + std::vector vec(str.size() + 1); + vec.assign(str.begin(), str.end()); + vec.push_back('\0'); + return vec; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace legacy_hal { +// Legacy HAL functions accept "C" style function pointers, so use global +// functions to pass to the legacy HAL function and store the corresponding +// std::function methods to be invoked. +// Callback to be invoked once |stop| is complete. +std::function on_stop_complete_internal_callback; +void onAsyncStopComplete(wifi_handle handle) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_stop_complete_internal_callback) { + on_stop_complete_internal_callback(handle); + // Invalidate this callback since we don't want this firing again. + on_stop_complete_internal_callback = nullptr; + } +} + +// Callback to be invoked for driver dump. +std::function on_driver_memory_dump_internal_callback; +void onSyncDriverMemoryDump(char* buffer, int buffer_size) { + if (on_driver_memory_dump_internal_callback) { + on_driver_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for firmware dump. +std::function on_firmware_memory_dump_internal_callback; +void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) { + if (on_firmware_memory_dump_internal_callback) { + on_firmware_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for Gscan events. +std::function + on_gscan_event_internal_callback; +void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_event_internal_callback) { + on_gscan_event_internal_callback(id, event); + } +} + +// Callback to be invoked for Gscan full results. +std::function + on_gscan_full_result_internal_callback; +void onAsyncGscanFullResult(wifi_request_id id, + wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_full_result_internal_callback) { + on_gscan_full_result_internal_callback(id, result, buckets_scanned); + } +} + +// Callback to be invoked for link layer stats results. +std::function + on_link_layer_stats_result_internal_callback; +void onSyncLinkLayerStatsResult(wifi_request_id id, + wifi_iface_stat* iface_stat, + int num_radios, + wifi_radio_stat* radio_stat) { + if (on_link_layer_stats_result_internal_callback) { + on_link_layer_stats_result_internal_callback( + id, iface_stat, num_radios, radio_stat); + } +} + +// Callback to be invoked for rssi threshold breach. +std::function + on_rssi_threshold_breached_internal_callback; +void onAsyncRssiThresholdBreached(wifi_request_id id, + uint8_t* bssid, + int8_t rssi) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rssi_threshold_breached_internal_callback) { + on_rssi_threshold_breached_internal_callback(id, bssid, rssi); + } +} + +// Callback to be invoked for ring buffer data indication. +std::function + on_ring_buffer_data_internal_callback; +void onAsyncRingBufferData(char* ring_name, + char* buffer, + int buffer_size, + wifi_ring_buffer_status* status) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_ring_buffer_data_internal_callback) { + on_ring_buffer_data_internal_callback( + ring_name, buffer, buffer_size, status); + } +} + +// Callback to be invoked for error alert indication. +std::function + on_error_alert_internal_callback; +void onAsyncErrorAlert(wifi_request_id id, + char* buffer, + int buffer_size, + int err_code) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_error_alert_internal_callback) { + on_error_alert_internal_callback(id, buffer, buffer_size, err_code); + } +} + +// Callback to be invoked for rtt results results. +std::function + on_rtt_results_internal_callback; +void onAsyncRttResults(wifi_request_id id, + unsigned num_results, + wifi_rtt_result* rtt_results[]) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rtt_results_internal_callback) { + on_rtt_results_internal_callback(id, num_results, rtt_results); + on_rtt_results_internal_callback = nullptr; + } +} + +// Callbacks for the various NAN operations. +// NOTE: These have very little conversions to perform before invoking the user +// callbacks. +// So, handle all of them here directly to avoid adding an unnecessary layer. +std::function + on_nan_notify_response_user_callback; +void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_notify_response_user_callback && msg) { + on_nan_notify_response_user_callback(id, *msg); + } +} + +std::function + on_nan_event_publish_replied_user_callback; +void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) { + LOG(ERROR) << "onAysncNanEventPublishReplied triggered"; +} + +std::function + on_nan_event_publish_terminated_user_callback; +void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_publish_terminated_user_callback && event) { + on_nan_event_publish_terminated_user_callback(*event); + } +} + +std::function on_nan_event_match_user_callback; +void onAysncNanEventMatch(NanMatchInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_user_callback && event) { + on_nan_event_match_user_callback(*event); + } +} + +std::function + on_nan_event_match_expired_user_callback; +void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_expired_user_callback && event) { + on_nan_event_match_expired_user_callback(*event); + } +} + +std::function + on_nan_event_subscribe_terminated_user_callback; +void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_subscribe_terminated_user_callback && event) { + on_nan_event_subscribe_terminated_user_callback(*event); + } +} + +std::function on_nan_event_followup_user_callback; +void onAysncNanEventFollowup(NanFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_followup_user_callback && event) { + on_nan_event_followup_user_callback(*event); + } +} + +std::function + on_nan_event_disc_eng_event_user_callback; +void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disc_eng_event_user_callback && event) { + on_nan_event_disc_eng_event_user_callback(*event); + } +} + +std::function on_nan_event_disabled_user_callback; +void onAysncNanEventDisabled(NanDisabledInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disabled_user_callback && event) { + on_nan_event_disabled_user_callback(*event); + } +} + +std::function on_nan_event_tca_user_callback; +void onAysncNanEventTca(NanTCAInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_tca_user_callback && event) { + on_nan_event_tca_user_callback(*event); + } +} + +std::function + on_nan_event_beacon_sdf_payload_user_callback; +void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_beacon_sdf_payload_user_callback && event) { + on_nan_event_beacon_sdf_payload_user_callback(*event); + } +} + +std::function + on_nan_event_data_path_request_user_callback; +void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_request_user_callback && event) { + on_nan_event_data_path_request_user_callback(*event); + } +} +std::function + on_nan_event_data_path_confirm_user_callback; +void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_confirm_user_callback && event) { + on_nan_event_data_path_confirm_user_callback(*event); + } +} + +std::function + on_nan_event_data_path_end_user_callback; +void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_end_user_callback && event) { + on_nan_event_data_path_end_user_callback(*event); + } +} + +std::function + on_nan_event_transmit_follow_up_user_callback; +void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_transmit_follow_up_user_callback && event) { + on_nan_event_transmit_follow_up_user_callback(*event); + } +} + +std::function + on_nan_event_range_request_user_callback; +void onAysncNanEventRangeRequest(NanRangeRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_request_user_callback && event) { + on_nan_event_range_request_user_callback(*event); + } +} + +std::function + on_nan_event_range_report_user_callback; +void onAysncNanEventRangeReport(NanRangeReportInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_report_user_callback && event) { + on_nan_event_range_report_user_callback(*event); + } +} +// End of the free-standing "C" style callbacks. + +WifiLegacyHal::WifiLegacyHal() + : global_handle_(nullptr), + wlan_interface_handle_(nullptr), + awaiting_event_loop_termination_(false), + is_started_(false) {} + +wifi_error WifiLegacyHal::initialize() { + LOG(DEBUG) << "Initialize legacy HAL"; + // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool + // for now is this function call which we can directly call. + if (!initHalFuncTableWithStubs(&global_func_table_)) { + LOG(ERROR) << "Failed to initialize legacy hal function table with stubs"; + return WIFI_ERROR_UNKNOWN; + } + wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_); + if (status != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to initialize legacy hal function table"; + } + return status; +} + +wifi_error WifiLegacyHal::start() { + // Ensure that we're starting in a good state. + CHECK(global_func_table_.wifi_initialize && !global_handle_ && + !wlan_interface_handle_ && !awaiting_event_loop_termination_); + if (is_started_) { + LOG(DEBUG) << "Legacy HAL already started"; + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Starting legacy HAL"; + if (!iface_tool_.SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } + wifi_error status = global_func_table_.wifi_initialize(&global_handle_); + if (status != WIFI_SUCCESS || !global_handle_) { + LOG(ERROR) << "Failed to retrieve global handle"; + return status; + } + std::thread(&WifiLegacyHal::runEventLoop, this).detach(); + status = retrieveWlanInterfaceHandle(); + if (status != WIFI_SUCCESS || !wlan_interface_handle_) { + LOG(ERROR) << "Failed to retrieve wlan interface handle"; + return status; + } + LOG(DEBUG) << "Legacy HAL start complete"; + is_started_ = true; + return WIFI_SUCCESS; +} + +wifi_error WifiLegacyHal::stop( + const std::function& on_stop_complete_user_callback) { + if (!is_started_) { + LOG(DEBUG) << "Legacy HAL already stopped"; + on_stop_complete_user_callback(); + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Stopping legacy HAL"; + on_stop_complete_internal_callback = [on_stop_complete_user_callback, + this](wifi_handle handle) { + CHECK_EQ(global_handle_, handle) << "Handle mismatch"; + // Invalidate all the internal pointers now that the HAL is + // stopped. + invalidate(); + iface_tool_.SetWifiUpState(false); + on_stop_complete_user_callback(); + }; + awaiting_event_loop_termination_ = true; + global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete); + LOG(DEBUG) << "Legacy HAL stop complete"; + is_started_ = false; + return WIFI_SUCCESS; +} + +std::string WifiLegacyHal::getApIfaceName() { + // Fake name. This interface does not exist in legacy HAL + // API's. + return "ap0"; +} + +std::string WifiLegacyHal::getNanIfaceName() { + // Fake name. This interface does not exist in legacy HAL + // API's. + return "nan0"; +} + +std::string WifiLegacyHal::getP2pIfaceName() { + std::array buffer; + property_get("wifi.direct.interface", buffer.data(), "p2p0"); + return buffer.data(); +} + +std::string WifiLegacyHal::getStaIfaceName() { + std::array buffer; + property_get("wifi.interface", buffer.data(), "wlan0"); + return buffer.data(); +} + +std::pair WifiLegacyHal::getDriverVersion() { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_driver_version( + wlan_interface_handle_, buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair WifiLegacyHal::getFirmwareVersion() { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_firmware_version( + wlan_interface_handle_, buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair> +WifiLegacyHal::requestDriverMemoryDump() { + std::vector driver_dump; + on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, + int buffer_size) { + driver_dump.insert(driver_dump.end(), + reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_driver_memory_dump( + wlan_interface_handle_, {onSyncDriverMemoryDump}); + on_driver_memory_dump_internal_callback = nullptr; + return {status, std::move(driver_dump)}; +} + +std::pair> +WifiLegacyHal::requestFirmwareMemoryDump() { + std::vector firmware_dump; + on_firmware_memory_dump_internal_callback = [&firmware_dump]( + char* buffer, int buffer_size) { + firmware_dump.insert(firmware_dump.end(), + reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_firmware_memory_dump( + wlan_interface_handle_, {onSyncFirmwareMemoryDump}); + on_firmware_memory_dump_internal_callback = nullptr; + return {status, std::move(firmware_dump)}; +} + +std::pair WifiLegacyHal::getSupportedFeatureSet() { + feature_set set; + static_assert(sizeof(set) == sizeof(uint32_t), + "Some features can not be represented in output"); + wifi_error status = global_func_table_.wifi_get_supported_feature_set( + wlan_interface_handle_, &set); + return {status, static_cast(set)}; +} + +std::pair +WifiLegacyHal::getPacketFilterCapabilities() { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + wlan_interface_handle_, &caps.version, &caps.max_len); + return {status, caps}; +} + +wifi_error WifiLegacyHal::setPacketFilter(const std::vector& program) { + return global_func_table_.wifi_set_packet_filter( + wlan_interface_handle_, program.data(), program.size()); +} + +std::pair +WifiLegacyHal::getGscanCapabilities() { + wifi_gscan_capabilities caps; + wifi_error status = global_func_table_.wifi_get_gscan_capabilities( + wlan_interface_handle_, &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::startGscan( + wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function& on_failure_user_callback, + const on_gscan_results_callback& on_results_user_callback, + const on_gscan_full_result_callback& on_full_result_user_callback) { + // If there is already an ongoing background scan, reject new scan requests. + if (on_gscan_event_internal_callback || + on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + // This callback will be used to either trigger |on_results_user_callback| or + // |on_failure_user_callback|. + on_gscan_event_internal_callback = + [on_failure_user_callback, on_results_user_callback, this]( + wifi_request_id id, wifi_scan_event event) { + switch (event) { + case WIFI_SCAN_RESULTS_AVAILABLE: + case WIFI_SCAN_THRESHOLD_NUM_SCANS: + case WIFI_SCAN_THRESHOLD_PERCENT: { + wifi_error status; + std::vector cached_scan_results; + std::tie(status, cached_scan_results) = getGscanCachedResults(); + if (status == WIFI_SUCCESS) { + on_results_user_callback(id, cached_scan_results); + return; + } + } + // Fall through if failed. Failure to retrieve cached scan results + // should trigger a background scan failure. + case WIFI_SCAN_FAILED: + on_failure_user_callback(id); + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + return; + } + LOG(FATAL) << "Unexpected gscan event received: " << event; + }; + + on_gscan_full_result_internal_callback = [on_full_result_user_callback]( + wifi_request_id id, wifi_scan_result* result, uint32_t buckets_scanned) { + if (result) { + on_full_result_user_callback(id, result, buckets_scanned); + } + }; + + wifi_scan_result_handler handler = {onAsyncGscanFullResult, + onAsyncGscanEvent}; + wifi_error status = global_func_table_.wifi_start_gscan( + id, wlan_interface_handle_, params, handler); + if (status != WIFI_SUCCESS) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopGscan(wifi_request_id id) { + // If there is no an ongoing background scan, reject stop requests. + // TODO(b/32337212): This needs to be handled by the HIDL object because we + // need to return the NOT_STARTED error code. + if (!on_gscan_event_internal_callback && + !on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = + global_func_table_.wifi_stop_gscan(id, wlan_interface_handle_); + // If the request Id is wrong, don't stop the ongoing background scan. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +std::pair> +WifiLegacyHal::getValidFrequenciesForBand(wifi_band band) { + static_assert(sizeof(uint32_t) >= sizeof(wifi_channel), + "Wifi Channel cannot be represented in output"); + std::vector freqs; + freqs.resize(kMaxGscanFrequenciesForBand); + int32_t num_freqs = 0; + wifi_error status = global_func_table_.wifi_get_valid_channels( + wlan_interface_handle_, + band, + freqs.size(), + reinterpret_cast(freqs.data()), + &num_freqs); + CHECK(num_freqs >= 0 && + static_cast(num_freqs) <= kMaxGscanFrequenciesForBand); + freqs.resize(num_freqs); + return {status, std::move(freqs)}; +} + +wifi_error WifiLegacyHal::setDfsFlag(bool dfs_on) { + return global_func_table_.wifi_set_nodfs_flag( + wlan_interface_handle_, dfs_on ? 0 : 1); +} + +wifi_error WifiLegacyHal::enableLinkLayerStats(bool debug) { + wifi_link_layer_params params; + params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold; + params.aggressive_statistics_gathering = debug; + return global_func_table_.wifi_set_link_stats(wlan_interface_handle_, params); +} + +wifi_error WifiLegacyHal::disableLinkLayerStats() { + // TODO: Do we care about these responses? + uint32_t clear_mask_rsp; + uint8_t stop_rsp; + return global_func_table_.wifi_clear_link_stats( + wlan_interface_handle_, 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp); +} + +std::pair WifiLegacyHal::getLinkLayerStats() { + LinkLayerStats link_stats{}; + LinkLayerStats* link_stats_ptr = &link_stats; + + on_link_layer_stats_result_internal_callback = + [&link_stats_ptr](wifi_request_id /* id */, + wifi_iface_stat* iface_stats_ptr, + int num_radios, + wifi_radio_stat* radio_stats_ptr) { + if (iface_stats_ptr != nullptr) { + link_stats_ptr->iface = *iface_stats_ptr; + link_stats_ptr->iface.num_peers = 0; + } else { + LOG(ERROR) << "Invalid iface stats in link layer stats"; + } + if (num_radios <= 0 || radio_stats_ptr == nullptr) { + LOG(ERROR) << "Invalid radio stats in link layer stats"; + return; + } + for (int i = 0; i < num_radios; i++) { + LinkLayerRadioStats radio; + radio.stats = radio_stats_ptr[i]; + // Copy over the tx level array to the separate vector. + if (radio_stats_ptr[i].num_tx_levels > 0 && + radio_stats_ptr[i].tx_time_per_levels != nullptr) { + radio.tx_time_per_levels.assign( + radio_stats_ptr[i].tx_time_per_levels, + radio_stats_ptr[i].tx_time_per_levels + + radio_stats_ptr[i].num_tx_levels); + } + radio.stats.num_tx_levels = 0; + radio.stats.tx_time_per_levels = nullptr; + link_stats_ptr->radios.push_back(radio); + } + }; + + wifi_error status = global_func_table_.wifi_get_link_stats( + 0, wlan_interface_handle_, {onSyncLinkLayerStatsResult}); + on_link_layer_stats_result_internal_callback = nullptr; + return {status, link_stats}; +} + +wifi_error WifiLegacyHal::startRssiMonitoring( + wifi_request_id id, + int8_t max_rssi, + int8_t min_rssi, + const on_rssi_threshold_breached_callback& + on_threshold_breached_user_callback) { + if (on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_rssi_threshold_breached_internal_callback = + [on_threshold_breached_user_callback]( + wifi_request_id id, uint8_t* bssid_ptr, int8_t rssi) { + if (!bssid_ptr) { + return; + } + std::array bssid_arr; + // |bssid_ptr| pointer is assumed to have 6 bytes for the mac address. + std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr)); + on_threshold_breached_user_callback(id, bssid_arr, rssi); + }; + wifi_error status = global_func_table_.wifi_start_rssi_monitoring( + id, + wlan_interface_handle_, + max_rssi, + min_rssi, + {onAsyncRssiThresholdBreached}); + if (status != WIFI_SUCCESS) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopRssiMonitoring(wifi_request_id id) { + if (!on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = + global_func_table_.wifi_stop_rssi_monitoring(id, wlan_interface_handle_); + // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +std::pair +WifiLegacyHal::getRoamingCapabilities() { + wifi_roaming_capabilities caps; + wifi_error status = global_func_table_.wifi_get_roaming_capabilities( + wlan_interface_handle_, &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::configureRoaming(const wifi_roaming_config& config) { + wifi_roaming_config config_internal = config; + return global_func_table_.wifi_configure_roaming(wlan_interface_handle_, + &config_internal); +} + +wifi_error WifiLegacyHal::enableFirmwareRoaming(fw_roaming_state_t state) { + return global_func_table_.wifi_enable_firmware_roaming(wlan_interface_handle_, + state); +} + +wifi_error WifiLegacyHal::configureNdOffload(bool enable) { + return global_func_table_.wifi_configure_nd_offload(wlan_interface_handle_, + enable); +} + +wifi_error WifiLegacyHal::startSendingOffloadedPacket( + uint32_t cmd_id, + const std::vector& ip_packet_data, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms) { + std::vector ip_packet_data_internal(ip_packet_data); + std::vector src_address_internal( + src_address.data(), src_address.data() + src_address.size()); + std::vector dst_address_internal( + dst_address.data(), dst_address.data() + dst_address.size()); + return global_func_table_.wifi_start_sending_offloaded_packet( + cmd_id, + wlan_interface_handle_, + ip_packet_data_internal.data(), + ip_packet_data_internal.size(), + src_address_internal.data(), + dst_address_internal.data(), + period_in_ms); +} + +wifi_error WifiLegacyHal::stopSendingOffloadedPacket(uint32_t cmd_id) { + return global_func_table_.wifi_stop_sending_offloaded_packet( + cmd_id, wlan_interface_handle_); +} + +wifi_error WifiLegacyHal::setScanningMacOui(const std::array& oui) { + std::vector oui_internal(oui.data(), oui.data() + oui.size()); + return global_func_table_.wifi_set_scanning_mac_oui(wlan_interface_handle_, + oui_internal.data()); +} + +std::pair WifiLegacyHal::getLoggerSupportedFeatureSet() { + uint32_t supported_features; + wifi_error status = global_func_table_.wifi_get_logger_supported_feature_set( + wlan_interface_handle_, &supported_features); + return {status, supported_features}; +} + +wifi_error WifiLegacyHal::startPktFateMonitoring() { + return global_func_table_.wifi_start_pkt_fate_monitoring( + wlan_interface_handle_); +} + +std::pair> +WifiLegacyHal::getTxPktFates() { + std::vector tx_pkt_fates; + tx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = + global_func_table_.wifi_get_tx_pkt_fates(wlan_interface_handle_, + tx_pkt_fates.data(), + tx_pkt_fates.size(), + &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + tx_pkt_fates.resize(num_fates); + return {status, std::move(tx_pkt_fates)}; +} + +std::pair> +WifiLegacyHal::getRxPktFates() { + std::vector rx_pkt_fates; + rx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = + global_func_table_.wifi_get_rx_pkt_fates(wlan_interface_handle_, + rx_pkt_fates.data(), + rx_pkt_fates.size(), + &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + rx_pkt_fates.resize(num_fates); + return {status, std::move(rx_pkt_fates)}; +} + +std::pair WifiLegacyHal::getWakeReasonStats() { + WakeReasonStats stats; + stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + + // This legacy struct needs separate memory to store the variable sized wake + // reason types. + stats.wake_reason_cnt.cmd_event_wake_cnt = + reinterpret_cast(stats.cmd_event_wake_cnt.data()); + stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size(); + stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0; + stats.wake_reason_cnt.driver_fw_local_wake_cnt = + reinterpret_cast(stats.driver_fw_local_wake_cnt.data()); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = + stats.driver_fw_local_wake_cnt.size(); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0; + + wifi_error status = global_func_table_.wifi_get_wake_reason_stats( + wlan_interface_handle_, &stats.wake_reason_cnt); + + CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 && + static_cast(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.cmd_event_wake_cnt.resize( + stats.wake_reason_cnt.cmd_event_wake_cnt_used); + stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr; + + CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 && + static_cast( + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize( + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used); + stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr; + + return {status, stats}; +} + +wifi_error WifiLegacyHal::registerRingBufferCallbackHandler( + const on_ring_buffer_data_callback& on_user_data_callback) { + if (on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = [on_user_data_callback]( + char* ring_name, + char* buffer, + int buffer_size, + wifi_ring_buffer_status* status) { + if (status && buffer) { + std::vector buffer_vector( + reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + on_user_data_callback(ring_name, buffer_vector, *status); + } + }; + wifi_error status = global_func_table_.wifi_set_log_handler( + 0, wlan_interface_handle_, {onAsyncRingBufferData}); + if (status != WIFI_SUCCESS) { + on_ring_buffer_data_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler() { + if (!on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = nullptr; + return global_func_table_.wifi_reset_log_handler(0, wlan_interface_handle_); +} + +std::pair> +WifiLegacyHal::getRingBuffersStatus() { + std::vector ring_buffers_status; + ring_buffers_status.resize(kMaxRingBuffers); + uint32_t num_rings = kMaxRingBuffers; + wifi_error status = global_func_table_.wifi_get_ring_buffers_status( + wlan_interface_handle_, &num_rings, ring_buffers_status.data()); + CHECK(num_rings <= kMaxRingBuffers); + ring_buffers_status.resize(num_rings); + return {status, std::move(ring_buffers_status)}; +} + +wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& ring_name, + uint32_t verbose_level, + uint32_t max_interval_sec, + uint32_t min_data_size) { + return global_func_table_.wifi_start_logging(wlan_interface_handle_, + verbose_level, + 0, + max_interval_sec, + min_data_size, + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::getRingBufferData(const std::string& ring_name) { + return global_func_table_.wifi_get_ring_data(wlan_interface_handle_, + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler( + const on_error_alert_callback& on_user_alert_callback) { + if (on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = [on_user_alert_callback]( + wifi_request_id id, char* buffer, int buffer_size, int err_code) { + if (buffer) { + CHECK(id == 0); + on_user_alert_callback( + err_code, + std::vector( + reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size)); + } + }; + wifi_error status = global_func_table_.wifi_set_alert_handler( + 0, wlan_interface_handle_, {onAsyncErrorAlert}); + if (status != WIFI_SUCCESS) { + on_error_alert_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler() { + if (!on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = nullptr; + return global_func_table_.wifi_reset_alert_handler(0, wlan_interface_handle_); +} + +wifi_error WifiLegacyHal::startRttRangeRequest( + wifi_request_id id, + const std::vector& rtt_configs, + const on_rtt_results_callback& on_results_user_callback) { + if (on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_rtt_results_internal_callback = [on_results_user_callback]( + wifi_request_id id, + unsigned num_results, + wifi_rtt_result* rtt_results[]) { + if (num_results > 0 && !rtt_results) { + LOG(ERROR) << "Unexpected nullptr in RTT results"; + return; + } + std::vector rtt_results_vec; + std::copy_if( + rtt_results, + rtt_results + num_results, + back_inserter(rtt_results_vec), + [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; }); + on_results_user_callback(id, rtt_results_vec); + }; + + std::vector rtt_configs_internal(rtt_configs); + wifi_error status = + global_func_table_.wifi_rtt_range_request(id, + wlan_interface_handle_, + rtt_configs.size(), + rtt_configs_internal.data(), + {onAsyncRttResults}); + if (status != WIFI_SUCCESS) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::cancelRttRangeRequest( + wifi_request_id id, const std::vector>& mac_addrs) { + if (!on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + static_assert(sizeof(mac_addr) == sizeof(std::array), + "MAC address size mismatch"); + // TODO: How do we handle partial cancels (i.e only a subset of enabled mac + // addressed are cancelled). + std::vector> mac_addrs_internal(mac_addrs); + wifi_error status = global_func_table_.wifi_rtt_range_cancel( + id, + wlan_interface_handle_, + mac_addrs.size(), + reinterpret_cast(mac_addrs_internal.data())); + // If the request Id is wrong, don't stop the ongoing range request. Any + // other error should be treated as the end of rtt ranging. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +std::pair +WifiLegacyHal::getRttCapabilities() { + wifi_rtt_capabilities rtt_caps; + wifi_error status = global_func_table_.wifi_get_rtt_capabilities( + wlan_interface_handle_, &rtt_caps); + return {status, rtt_caps}; +} + +std::pair WifiLegacyHal::getRttResponderInfo() { + wifi_rtt_responder rtt_responder; + wifi_error status = global_func_table_.wifi_rtt_get_responder_info( + wlan_interface_handle_, &rtt_responder); + return {status, rtt_responder}; +} + +wifi_error WifiLegacyHal::enableRttResponder( + wifi_request_id id, + const wifi_channel_info& channel_hint, + uint32_t max_duration_secs, + const wifi_rtt_responder& info) { + wifi_rtt_responder info_internal(info); + return global_func_table_.wifi_enable_responder(id, + wlan_interface_handle_, + channel_hint, + max_duration_secs, + &info_internal); +} + +wifi_error WifiLegacyHal::disableRttResponder(wifi_request_id id) { + return global_func_table_.wifi_disable_responder(id, wlan_interface_handle_); +} + +wifi_error WifiLegacyHal::setRttLci(wifi_request_id id, + const wifi_lci_information& info) { + wifi_lci_information info_internal(info); + return global_func_table_.wifi_set_lci( + id, wlan_interface_handle_, &info_internal); +} + +wifi_error WifiLegacyHal::setRttLcr(wifi_request_id id, + const wifi_lcr_information& info) { + wifi_lcr_information info_internal(info); + return global_func_table_.wifi_set_lcr( + id, wlan_interface_handle_, &info_internal); +} + +wifi_error WifiLegacyHal::nanRegisterCallbackHandlers( + const NanCallbackHandlers& user_callbacks) { + on_nan_notify_response_user_callback = user_callbacks.on_notify_response; + on_nan_event_publish_terminated_user_callback = + user_callbacks.on_event_publish_terminated; + on_nan_event_match_user_callback = user_callbacks.on_event_match; + on_nan_event_match_expired_user_callback = + user_callbacks.on_event_match_expired; + on_nan_event_subscribe_terminated_user_callback = + user_callbacks.on_event_subscribe_terminated; + on_nan_event_followup_user_callback = user_callbacks.on_event_followup; + on_nan_event_disc_eng_event_user_callback = + user_callbacks.on_event_disc_eng_event; + on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled; + on_nan_event_tca_user_callback = user_callbacks.on_event_tca; + on_nan_event_beacon_sdf_payload_user_callback = + user_callbacks.on_event_beacon_sdf_payload; + on_nan_event_data_path_request_user_callback = + user_callbacks.on_event_data_path_request; + on_nan_event_data_path_confirm_user_callback = + user_callbacks.on_event_data_path_confirm; + on_nan_event_data_path_end_user_callback = + user_callbacks.on_event_data_path_end; + on_nan_event_transmit_follow_up_user_callback = + user_callbacks.on_event_transmit_follow_up; + on_nan_event_range_request_user_callback = + user_callbacks.on_event_range_request; + on_nan_event_range_report_user_callback = + user_callbacks.on_event_range_report; + + return global_func_table_.wifi_nan_register_handler( + wlan_interface_handle_, + {onAysncNanNotifyResponse, + onAysncNanEventPublishReplied, + onAysncNanEventPublishTerminated, + onAysncNanEventMatch, + onAysncNanEventMatchExpired, + onAysncNanEventSubscribeTerminated, + onAysncNanEventFollowup, + onAysncNanEventDiscEngEvent, + onAysncNanEventDisabled, + onAysncNanEventTca, + onAysncNanEventBeaconSdfPayload, + onAysncNanEventDataPathRequest, + onAysncNanEventDataPathConfirm, + onAysncNanEventDataPathEnd, + onAysncNanEventTransmitFollowUp, + onAysncNanEventRangeRequest, + onAysncNanEventRangeReport}); +} + +wifi_error WifiLegacyHal::nanEnableRequest(transaction_id id, + const NanEnableRequest& msg) { + NanEnableRequest msg_internal(msg); + return global_func_table_.wifi_nan_enable_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanDisableRequest(transaction_id id) { + return global_func_table_.wifi_nan_disable_request(id, + wlan_interface_handle_); +} + +wifi_error WifiLegacyHal::nanPublishRequest(transaction_id id, + const NanPublishRequest& msg) { + NanPublishRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanPublishCancelRequest( + transaction_id id, const NanPublishCancelRequest& msg) { + NanPublishCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_cancel_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeRequest(transaction_id id, + const NanSubscribeRequest& msg) { + NanSubscribeRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeCancelRequest( + transaction_id id, const NanSubscribeCancelRequest& msg) { + NanSubscribeCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_cancel_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanTransmitFollowupRequest( + transaction_id id, const NanTransmitFollowupRequest& msg) { + NanTransmitFollowupRequest msg_internal(msg); + return global_func_table_.wifi_nan_transmit_followup_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanStatsRequest(transaction_id id, + const NanStatsRequest& msg) { + NanStatsRequest msg_internal(msg); + return global_func_table_.wifi_nan_stats_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanConfigRequest(transaction_id id, + const NanConfigRequest& msg) { + NanConfigRequest msg_internal(msg); + return global_func_table_.wifi_nan_config_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanTcaRequest(transaction_id id, + const NanTCARequest& msg) { + NanTCARequest msg_internal(msg); + return global_func_table_.wifi_nan_tca_request( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest( + transaction_id id, const NanBeaconSdfPayloadRequest& msg) { + NanBeaconSdfPayloadRequest msg_internal(msg); + return global_func_table_.wifi_nan_beacon_sdf_payload_request( + id, wlan_interface_handle_, &msg_internal); +} + +std::pair WifiLegacyHal::nanGetVersion() { + NanVersion version; + wifi_error status = + global_func_table_.wifi_nan_get_version(global_handle_, &version); + return {status, version}; +} + +wifi_error WifiLegacyHal::nanGetCapabilities(transaction_id id) { + return global_func_table_.wifi_nan_get_capabilities(id, + wlan_interface_handle_); +} + +wifi_error WifiLegacyHal::nanDataInterfaceCreate( + transaction_id id, const std::string& iface_name) { + return global_func_table_.wifi_nan_data_interface_create( + id, wlan_interface_handle_, makeCharVec(iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataInterfaceDelete( + transaction_id id, const std::string& iface_name) { + return global_func_table_.wifi_nan_data_interface_delete( + id, wlan_interface_handle_, makeCharVec(iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataRequestInitiator( + transaction_id id, const NanDataPathInitiatorRequest& msg) { + NanDataPathInitiatorRequest msg_internal(msg); + return global_func_table_.wifi_nan_data_request_initiator( + id, wlan_interface_handle_, &msg_internal); +} + +wifi_error WifiLegacyHal::nanDataIndicationResponse( + transaction_id id, const NanDataPathIndicationResponse& msg) { + NanDataPathIndicationResponse msg_internal(msg); + return global_func_table_.wifi_nan_data_indication_response( + id, wlan_interface_handle_, &msg_internal); +} + +typedef struct { + u8 num_ndp_instances; + NanDataPathId ndp_instance_id; +} NanDataPathEndSingleNdpIdRequest; + +wifi_error WifiLegacyHal::nanDataEnd(transaction_id id, + uint32_t ndpInstanceId) { + NanDataPathEndSingleNdpIdRequest msg; + msg.num_ndp_instances = 1; + msg.ndp_instance_id = ndpInstanceId; + wifi_error status = global_func_table_.wifi_nan_data_end( + id, wlan_interface_handle_, (NanDataPathEndRequest*)&msg); + return status; +} + +wifi_error WifiLegacyHal::setCountryCode(std::array code) { + std::string code_str(code.data(), code.data() + code.size()); + return global_func_table_.wifi_set_country_code(wlan_interface_handle_, + code_str.c_str()); +} + +wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() { + const std::string& ifname_to_find = getStaIfaceName(); + wifi_interface_handle* iface_handles = nullptr; + int num_iface_handles = 0; + wifi_error status = global_func_table_.wifi_get_ifaces( + global_handle_, &num_iface_handles, &iface_handles); + if (status != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to enumerate interface handles"; + return status; + } + for (int i = 0; i < num_iface_handles; ++i) { + std::array current_ifname; + current_ifname.fill(0); + status = global_func_table_.wifi_get_iface_name( + iface_handles[i], current_ifname.data(), current_ifname.size()); + if (status != WIFI_SUCCESS) { + LOG(WARNING) << "Failed to get interface handle name"; + continue; + } + if (ifname_to_find == current_ifname.data()) { + wlan_interface_handle_ = iface_handles[i]; + return WIFI_SUCCESS; + } + } + return WIFI_ERROR_UNKNOWN; +} + +void WifiLegacyHal::runEventLoop() { + LOG(DEBUG) << "Starting legacy HAL event loop"; + global_func_table_.wifi_event_loop(global_handle_); + if (!awaiting_event_loop_termination_) { + LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping"; + } + LOG(DEBUG) << "Legacy HAL event loop terminated"; + awaiting_event_loop_termination_ = false; +} + +std::pair> +WifiLegacyHal::getGscanCachedResults() { + std::vector cached_scan_results; + cached_scan_results.resize(kMaxCachedGscanResults); + int32_t num_results = 0; + wifi_error status = global_func_table_.wifi_get_cached_gscan_results( + wlan_interface_handle_, + true /* always flush */, + cached_scan_results.size(), + cached_scan_results.data(), + &num_results); + CHECK(num_results >= 0 && + static_cast(num_results) <= kMaxCachedGscanResults); + cached_scan_results.resize(num_results); + // Check for invalid IE lengths in these cached scan results and correct it. + for (auto& cached_scan_result : cached_scan_results) { + int num_scan_results = cached_scan_result.num_results; + for (int i = 0; i < num_scan_results; i++) { + auto& scan_result = cached_scan_result.results[i]; + if (scan_result.ie_length > 0) { + LOG(ERROR) << "Cached scan result has non-zero IE length " + << scan_result.ie_length; + scan_result.ie_length = 0; + } + } + } + return {status, std::move(cached_scan_results)}; +} + +void WifiLegacyHal::invalidate() { + global_handle_ = nullptr; + wlan_interface_handle_ = nullptr; + on_driver_memory_dump_internal_callback = nullptr; + on_firmware_memory_dump_internal_callback = nullptr; + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + on_link_layer_stats_result_internal_callback = nullptr; + on_rssi_threshold_breached_internal_callback = nullptr; + on_ring_buffer_data_internal_callback = nullptr; + on_error_alert_internal_callback = nullptr; + on_rtt_results_internal_callback = nullptr; + on_nan_notify_response_user_callback = nullptr; + on_nan_event_publish_terminated_user_callback = nullptr; + on_nan_event_match_user_callback = nullptr; + on_nan_event_match_expired_user_callback = nullptr; + on_nan_event_subscribe_terminated_user_callback = nullptr; + on_nan_event_followup_user_callback = nullptr; + on_nan_event_disc_eng_event_user_callback = nullptr; + on_nan_event_disabled_user_callback = nullptr; + on_nan_event_tca_user_callback = nullptr; + on_nan_event_beacon_sdf_payload_user_callback = nullptr; + on_nan_event_data_path_request_user_callback = nullptr; + on_nan_event_data_path_confirm_user_callback = nullptr; + on_nan_event_data_path_end_user_callback = nullptr; + on_nan_event_transmit_follow_up_user_callback = nullptr; + on_nan_event_range_request_user_callback = nullptr; + on_nan_event_range_report_user_callback = nullptr; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h new file mode 100644 index 000000000..fef7999c0 --- /dev/null +++ b/wifi/1.1/default/wifi_legacy_hal.h @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_LEGACY_HAL_H_ +#define WIFI_LEGACY_HAL_H_ + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +// This is in a separate namespace to prevent typename conflicts between +// the legacy HAL types and the HIDL interface types. +namespace legacy_hal { +// Wrap all the types defined inside the legacy HAL header files inside this +// namespace. +#include + +// APF capabilities supported by the iface. +struct PacketFilterCapabilities { + uint32_t version; + uint32_t max_len; +}; + +// WARNING: We don't care about the variable sized members of either +// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma +// to escape the compiler warnings regarding this. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end" +// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in +// |wifi_radio_stat| structure in the legacy HAL API. Separate that out +// into a separate return element to avoid passing pointers around. +struct LinkLayerRadioStats { + wifi_radio_stat stats; + std::vector tx_time_per_levels; +}; + +struct LinkLayerStats { + wifi_iface_stat iface; + std::vector radios; +}; +#pragma GCC diagnostic pop + +// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and +// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided +// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL +// API. Separate that out into a separate return elements to avoid passing +// pointers around. +struct WakeReasonStats { + WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt; + std::vector cmd_event_wake_cnt; + std::vector driver_fw_local_wake_cnt; +}; + +// NAN response and event callbacks struct. +struct NanCallbackHandlers { + // NotifyResponse invoked to notify the status of the Request. + std::function on_notify_response; + // Various event callbacks. + std::function + on_event_publish_terminated; + std::function on_event_match; + std::function on_event_match_expired; + std::function + on_event_subscribe_terminated; + std::function on_event_followup; + std::function on_event_disc_eng_event; + std::function on_event_disabled; + std::function on_event_tca; + std::function + on_event_beacon_sdf_payload; + std::function on_event_data_path_request; + std::function on_event_data_path_confirm; + std::function on_event_data_path_end; + std::function + on_event_transmit_follow_up; + std::function + on_event_range_request; + std::function + on_event_range_report; +}; + +// Full scan results contain IE info and are hence passed by reference, to +// preserve the variable length array member |ie_data|. Callee must not retain +// the pointer. +using on_gscan_full_result_callback = + std::function; +// These scan results don't contain any IE info, so no need to pass by +// reference. +using on_gscan_results_callback = std::function&)>; + +// Invoked when the rssi value breaches the thresholds set. +using on_rssi_threshold_breached_callback = + std::function, int8_t)>; + +// Callback for RTT range request results. +// Rtt results contain IE info and are hence passed by reference, to +// preserve the |LCI| and |LCR| pointers. Callee must not retain +// the pointer. +using on_rtt_results_callback = std::function&)>; + +// Callback for ring buffer data. +using on_ring_buffer_data_callback = + std::function&, + const wifi_ring_buffer_status&)>; + +// Callback for alerts. +using on_error_alert_callback = + std::function&)>; +/** + * Class that encapsulates all legacy HAL interactions. + * This class manages the lifetime of the event loop thread used by legacy HAL. + * + * Note: aThere will only be a single instance of this class created in the Wifi + * object and will be valid for the lifetime of the process. + */ +class WifiLegacyHal { + public: + WifiLegacyHal(); + // Names to use for the different types of iface. + std::string getApIfaceName(); + std::string getNanIfaceName(); + std::string getP2pIfaceName(); + std::string getStaIfaceName(); + + // Initialize the legacy HAL function table. + wifi_error initialize(); + // Start the legacy HAL and the event looper thread. + wifi_error start(); + // Deinitialize the legacy HAL and stop the event looper thread. + wifi_error stop(const std::function& on_complete_callback); + // Wrappers for all the functions in the legacy HAL function table. + std::pair getDriverVersion(); + std::pair getFirmwareVersion(); + std::pair> requestDriverMemoryDump(); + std::pair> requestFirmwareMemoryDump(); + std::pair getSupportedFeatureSet(); + // APF functions. + std::pair getPacketFilterCapabilities(); + wifi_error setPacketFilter(const std::vector& program); + // Gscan functions. + std::pair getGscanCapabilities(); + // These API's provides a simplified interface over the legacy Gscan API's: + // a) All scan events from the legacy HAL API other than the + // |WIFI_SCAN_FAILED| are treated as notification of results. + // This method then retrieves the cached scan results from the legacy + // HAL API and triggers the externally provided |on_results_user_callback| + // on success. + // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan results + // triggers the externally provided |on_failure_user_callback|. + // c) Full scan result event triggers the externally provided + // |on_full_result_user_callback|. + wifi_error startGscan( + wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function& on_failure_callback, + const on_gscan_results_callback& on_results_callback, + const on_gscan_full_result_callback& on_full_result_callback); + wifi_error stopGscan(wifi_request_id id); + std::pair> getValidFrequenciesForBand( + wifi_band band); + wifi_error setDfsFlag(bool dfs_on); + // Link layer stats functions. + wifi_error enableLinkLayerStats(bool debug); + wifi_error disableLinkLayerStats(); + std::pair getLinkLayerStats(); + // RSSI monitor functions. + wifi_error startRssiMonitoring(wifi_request_id id, + int8_t max_rssi, + int8_t min_rssi, + const on_rssi_threshold_breached_callback& + on_threshold_breached_callback); + wifi_error stopRssiMonitoring(wifi_request_id id); + std::pair getRoamingCapabilities(); + wifi_error configureRoaming(const wifi_roaming_config& config); + wifi_error enableFirmwareRoaming(fw_roaming_state_t state); + wifi_error configureNdOffload(bool enable); + wifi_error startSendingOffloadedPacket( + uint32_t cmd_id, + const std::vector& ip_packet_data, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms); + wifi_error stopSendingOffloadedPacket(uint32_t cmd_id); + wifi_error setScanningMacOui(const std::array& oui); + // Logger/debug functions. + std::pair getLoggerSupportedFeatureSet(); + wifi_error startPktFateMonitoring(); + std::pair> getTxPktFates(); + std::pair> getRxPktFates(); + std::pair getWakeReasonStats(); + wifi_error registerRingBufferCallbackHandler( + const on_ring_buffer_data_callback& on_data_callback); + wifi_error deregisterRingBufferCallbackHandler(); + std::pair> + getRingBuffersStatus(); + wifi_error startRingBufferLogging(const std::string& ring_name, + uint32_t verbose_level, + uint32_t max_interval_sec, + uint32_t min_data_size); + wifi_error getRingBufferData(const std::string& ring_name); + wifi_error registerErrorAlertCallbackHandler( + const on_error_alert_callback& on_alert_callback); + wifi_error deregisterErrorAlertCallbackHandler(); + // RTT functions. + wifi_error startRttRangeRequest( + wifi_request_id id, + const std::vector& rtt_configs, + const on_rtt_results_callback& on_results_callback); + wifi_error cancelRttRangeRequest( + wifi_request_id id, const std::vector>& mac_addrs); + std::pair getRttCapabilities(); + std::pair getRttResponderInfo(); + wifi_error enableRttResponder(wifi_request_id id, + const wifi_channel_info& channel_hint, + uint32_t max_duration_secs, + const wifi_rtt_responder& info); + wifi_error disableRttResponder(wifi_request_id id); + wifi_error setRttLci(wifi_request_id id, const wifi_lci_information& info); + wifi_error setRttLcr(wifi_request_id id, const wifi_lcr_information& info); + // NAN functions. + wifi_error nanRegisterCallbackHandlers(const NanCallbackHandlers& callbacks); + wifi_error nanEnableRequest(transaction_id id, const NanEnableRequest& msg); + wifi_error nanDisableRequest(transaction_id id); + wifi_error nanPublishRequest(transaction_id id, const NanPublishRequest& msg); + wifi_error nanPublishCancelRequest(transaction_id id, + const NanPublishCancelRequest& msg); + wifi_error nanSubscribeRequest(transaction_id id, + const NanSubscribeRequest& msg); + wifi_error nanSubscribeCancelRequest(transaction_id id, + const NanSubscribeCancelRequest& msg); + wifi_error nanTransmitFollowupRequest(transaction_id id, + const NanTransmitFollowupRequest& msg); + wifi_error nanStatsRequest(transaction_id id, const NanStatsRequest& msg); + wifi_error nanConfigRequest(transaction_id id, const NanConfigRequest& msg); + wifi_error nanTcaRequest(transaction_id id, const NanTCARequest& msg); + wifi_error nanBeaconSdfPayloadRequest(transaction_id id, + const NanBeaconSdfPayloadRequest& msg); + std::pair nanGetVersion(); + wifi_error nanGetCapabilities(transaction_id id); + wifi_error nanDataInterfaceCreate(transaction_id id, + const std::string& iface_name); + wifi_error nanDataInterfaceDelete(transaction_id id, + const std::string& iface_name); + wifi_error nanDataRequestInitiator(transaction_id id, + const NanDataPathInitiatorRequest& msg); + wifi_error nanDataIndicationResponse( + transaction_id id, const NanDataPathIndicationResponse& msg); + wifi_error nanDataEnd(transaction_id id, uint32_t ndpInstanceId); + // AP functions. + wifi_error setCountryCode(std::array code); + + private: + // Retrieve the interface handle to be used for the "wlan" interface. + wifi_error retrieveWlanInterfaceHandle(); + // Run the legacy HAL event loop thread. + void runEventLoop(); + // Retrieve the cached gscan results to pass the results back to the external + // callbacks. + std::pair> + getGscanCachedResults(); + void invalidate(); + + // Global function table of legacy HAL. + wifi_hal_fn global_func_table_; + // Opaque handle to be used for all global operations. + wifi_handle global_handle_; + // Opaque handle to be used for all wlan0 interface specific operations. + wifi_interface_handle wlan_interface_handle_; + // Flag to indicate if we have initiated the cleanup of legacy HAL. + std::atomic awaiting_event_loop_termination_; + // Flag to indicate if the legacy HAL has been started. + bool is_started_; + wifi_system::InterfaceTool iface_tool_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_H_ diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.cpp b/wifi/1.1/default/wifi_legacy_hal_stubs.cpp new file mode 100644 index 000000000..a5a5d4859 --- /dev/null +++ b/wifi/1.1/default/wifi_legacy_hal_stubs.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2016 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 "wifi_legacy_hal_stubs.h" + +// TODO: Remove these stubs from HalTool in libwifi-system. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace legacy_hal { +template +struct stubFunction; + +template +struct stubFunction { + static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; } +}; +template +struct stubFunction { + static constexpr void invoke(Args...) {} +}; + +template +void populateStubFor(T* val) { + *val = &stubFunction::invoke; +} + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { + if (hal_fn == nullptr) { + return false; + } + populateStubFor(&hal_fn->wifi_initialize); + populateStubFor(&hal_fn->wifi_cleanup); + populateStubFor(&hal_fn->wifi_event_loop); + populateStubFor(&hal_fn->wifi_get_error_info); + populateStubFor(&hal_fn->wifi_get_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_concurrency_matrix); + populateStubFor(&hal_fn->wifi_set_scanning_mac_oui); + populateStubFor(&hal_fn->wifi_get_supported_channels); + populateStubFor(&hal_fn->wifi_is_epr_supported); + populateStubFor(&hal_fn->wifi_get_ifaces); + populateStubFor(&hal_fn->wifi_get_iface_name); + populateStubFor(&hal_fn->wifi_set_iface_event_handler); + populateStubFor(&hal_fn->wifi_reset_iface_event_handler); + populateStubFor(&hal_fn->wifi_start_gscan); + populateStubFor(&hal_fn->wifi_stop_gscan); + populateStubFor(&hal_fn->wifi_get_cached_gscan_results); + populateStubFor(&hal_fn->wifi_set_bssid_hotlist); + populateStubFor(&hal_fn->wifi_reset_bssid_hotlist); + populateStubFor(&hal_fn->wifi_set_significant_change_handler); + populateStubFor(&hal_fn->wifi_reset_significant_change_handler); + populateStubFor(&hal_fn->wifi_get_gscan_capabilities); + populateStubFor(&hal_fn->wifi_set_link_stats); + populateStubFor(&hal_fn->wifi_get_link_stats); + populateStubFor(&hal_fn->wifi_clear_link_stats); + populateStubFor(&hal_fn->wifi_get_valid_channels); + populateStubFor(&hal_fn->wifi_rtt_range_request); + populateStubFor(&hal_fn->wifi_rtt_range_cancel); + populateStubFor(&hal_fn->wifi_get_rtt_capabilities); + populateStubFor(&hal_fn->wifi_rtt_get_responder_info); + populateStubFor(&hal_fn->wifi_enable_responder); + populateStubFor(&hal_fn->wifi_disable_responder); + populateStubFor(&hal_fn->wifi_set_nodfs_flag); + populateStubFor(&hal_fn->wifi_start_logging); + populateStubFor(&hal_fn->wifi_set_epno_list); + populateStubFor(&hal_fn->wifi_reset_epno_list); + populateStubFor(&hal_fn->wifi_set_country_code); + populateStubFor(&hal_fn->wifi_get_firmware_memory_dump); + populateStubFor(&hal_fn->wifi_set_log_handler); + populateStubFor(&hal_fn->wifi_reset_log_handler); + populateStubFor(&hal_fn->wifi_set_alert_handler); + populateStubFor(&hal_fn->wifi_reset_alert_handler); + populateStubFor(&hal_fn->wifi_get_firmware_version); + populateStubFor(&hal_fn->wifi_get_ring_buffers_status); + populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_ring_data); + populateStubFor(&hal_fn->wifi_enable_tdls); + populateStubFor(&hal_fn->wifi_disable_tdls); + populateStubFor(&hal_fn->wifi_get_tdls_status); + populateStubFor(&hal_fn->wifi_get_tdls_capabilities); + populateStubFor(&hal_fn->wifi_get_driver_version); + populateStubFor(&hal_fn->wifi_set_passpoint_list); + populateStubFor(&hal_fn->wifi_reset_passpoint_list); + populateStubFor(&hal_fn->wifi_set_lci); + populateStubFor(&hal_fn->wifi_set_lcr); + populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_start_rssi_monitoring); + populateStubFor(&hal_fn->wifi_stop_rssi_monitoring); + populateStubFor(&hal_fn->wifi_get_wake_reason_stats); + populateStubFor(&hal_fn->wifi_configure_nd_offload); + populateStubFor(&hal_fn->wifi_get_driver_memory_dump); + populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring); + populateStubFor(&hal_fn->wifi_get_tx_pkt_fates); + populateStubFor(&hal_fn->wifi_get_rx_pkt_fates); + populateStubFor(&hal_fn->wifi_nan_enable_request); + populateStubFor(&hal_fn->wifi_nan_disable_request); + populateStubFor(&hal_fn->wifi_nan_publish_request); + populateStubFor(&hal_fn->wifi_nan_publish_cancel_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request); + populateStubFor(&hal_fn->wifi_nan_transmit_followup_request); + populateStubFor(&hal_fn->wifi_nan_stats_request); + populateStubFor(&hal_fn->wifi_nan_config_request); + populateStubFor(&hal_fn->wifi_nan_tca_request); + populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request); + populateStubFor(&hal_fn->wifi_nan_register_handler); + populateStubFor(&hal_fn->wifi_nan_get_version); + populateStubFor(&hal_fn->wifi_nan_get_capabilities); + populateStubFor(&hal_fn->wifi_nan_data_interface_create); + populateStubFor(&hal_fn->wifi_nan_data_interface_delete); + populateStubFor(&hal_fn->wifi_nan_data_request_initiator); + populateStubFor(&hal_fn->wifi_nan_data_indication_response); + populateStubFor(&hal_fn->wifi_nan_data_end); + populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities); + populateStubFor(&hal_fn->wifi_set_packet_filter); + populateStubFor(&hal_fn->wifi_get_roaming_capabilities); + populateStubFor(&hal_fn->wifi_enable_firmware_roaming); + populateStubFor(&hal_fn->wifi_configure_roaming); + return true; +} +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.h b/wifi/1.1/default/wifi_legacy_hal_stubs.h new file mode 100644 index 000000000..bfc4c9b86 --- /dev/null +++ b/wifi/1.1/default/wifi_legacy_hal_stubs.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_LEGACY_HAL_STUBS_H_ +#define WIFI_LEGACY_HAL_STUBS_H_ + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace legacy_hal { +#include + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_STUBS_H_ diff --git a/wifi/1.1/default/wifi_mode_controller.cpp b/wifi/1.1/default/wifi_mode_controller.cpp new file mode 100644 index 000000000..b8a44c253 --- /dev/null +++ b/wifi/1.1/default/wifi_mode_controller.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 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 +#include +#include + +#include "wifi_mode_controller.h" + +using android::hardware::wifi::V1_0::IfaceType; +using android::wifi_hal::DriverTool; + +namespace { +int convertIfaceTypeToFirmwareMode(IfaceType type) { + int mode; + switch (type) { + case IfaceType::AP: + mode = DriverTool::kFirmwareModeAp; + break; + case IfaceType::P2P: + mode = DriverTool::kFirmwareModeP2p; + break; + case IfaceType::NAN: + // NAN is exposed in STA mode currently. + mode = DriverTool::kFirmwareModeSta; + break; + case IfaceType::STA: + mode = DriverTool::kFirmwareModeSta; + break; + } + return mode; +} +} + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace mode_controller { + +WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {} + +bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) { + return driver_tool_->IsFirmwareModeChangeNeeded( + convertIfaceTypeToFirmwareMode(type)); +} + +bool WifiModeController::changeFirmwareMode(IfaceType type) { + if (!driver_tool_->LoadDriver()) { + LOG(ERROR) << "Failed to load WiFi driver"; + return false; + } + if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) { + LOG(ERROR) << "Failed to change firmware mode"; + return false; + } + return true; +} + +bool WifiModeController::deinitialize() { + if (!driver_tool_->UnloadDriver()) { + LOG(ERROR) << "Failed to unload WiFi driver"; + return false; + } + return true; +} +} // namespace mode_controller +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_mode_controller.h b/wifi/1.1/default/wifi_mode_controller.h new file mode 100644 index 000000000..69845095b --- /dev/null +++ b/wifi/1.1/default/wifi_mode_controller.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_MODE_CONTROLLER_H_ +#define WIFI_MODE_CONTROLLER_H_ + +#include + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +namespace mode_controller { +using namespace android::hardware::wifi::V1_0; + +/** + * Class that encapsulates all firmware mode configuration. + * This class will perform the necessary firmware reloads to put the chip in the + * required state (essentially a wrapper over DriverTool). + */ +class WifiModeController { + public: + WifiModeController(); + + // Checks if a firmware mode change is necessary to support the specified + // iface type operations. + bool isFirmwareModeChangeNeeded(IfaceType type); + // Change the firmware mode to support the specified iface type operations. + bool changeFirmwareMode(IfaceType type); + // Unload the driver. This should be invoked whenever |IWifi.stop()| is + // invoked. + bool deinitialize(); + + private: + std::unique_ptr driver_tool_; +}; + +} // namespace mode_controller +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_MODE_CONTROLLER_H_ diff --git a/wifi/1.1/default/wifi_nan_iface.cpp b/wifi/1.1/default/wifi_nan_iface.cpp new file mode 100644 index 000000000..a111d0610 --- /dev/null +++ b/wifi/1.1/default/wifi_nan_iface.cpp @@ -0,0 +1,769 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_nan_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiNanIface::WifiNanIface( + const std::string& ifname, + const std::weak_ptr legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) { + // Register all the callbacks here. these should be valid for the lifetime + // of the object. Whenever the mode changes legacy HAL will remove + // all of these callbacks. + legacy_hal::NanCallbackHandlers callback_handlers; + android::wp weak_ptr_this(this); + + // Callback for response. + callback_handlers.on_notify_response = [weak_ptr_this]( + legacy_hal::transaction_id id, const legacy_hal::NanResponseMsg& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus wifiNanStatus; + if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg, + &wifiNanStatus)) { + LOG(ERROR) << "Failed to convert nan response header"; + return; + } + + switch (msg.response_type) { + case legacy_hal::NAN_RESPONSE_ENABLED: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyEnableResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_DISABLED: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyDisableResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStartPublishResponse(id, wifiNanStatus, + msg.body.publish_response.publish_id).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStopPublishResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyTransmitFollowupResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStartSubscribeResponse(id, wifiNanStatus, + msg.body.subscribe_response.subscribe_id).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStopSubscribeResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_CONFIG: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyConfigResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_GET_CAPABILITIES: { + NanCapabilities hidl_struct; + if (!hidl_struct_util::convertLegacyNanCapabilitiesResponseToHidl( + msg.body.nan_capabilities, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyCapabilitiesResponse(id, wifiNanStatus, + hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_CREATE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyCreateDataInterfaceResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_DELETE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyDeleteDataInterfaceResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INITIATOR_RESPONSE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyInitiateDataPathResponse(id, wifiNanStatus, + msg.body.data_request_response.ndp_instance_id).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_RESPONDER_RESPONSE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyRespondToDataPathIndicationResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_END: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyTerminateDataPathResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD: + /* fall through */ + case legacy_hal::NAN_RESPONSE_TCA: + /* fall through */ + case legacy_hal::NAN_RESPONSE_STATS: + /* fall through */ + case legacy_hal::NAN_RESPONSE_ERROR: + /* fall through */ + default: + LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type; + return; + } + }; + + callback_handlers.on_event_disc_eng_event = [weak_ptr_this]( + const legacy_hal::NanDiscEngEventInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanClusterEventInd hidl_struct; + // event types defined identically - hence can be cast + hidl_struct.eventType = (NanClusterEventType) msg.event_type; + hidl_struct.addr = msg.data.mac_addr.addr; + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventClusterEvent(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_disabled = [weak_ptr_this]( + const legacy_hal::NanDisabledInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason), + &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_publish_terminated = [weak_ptr_this]( + const legacy_hal::NanPublishTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason), + &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_subscribe_terminated = [weak_ptr_this]( + const legacy_hal::NanSubscribeTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason), + &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match = [weak_ptr_this]( + const legacy_hal::NanMatchInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanMatchInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanMatchIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventMatch(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match_expired = [weak_ptr_this]( + const legacy_hal::NanMatchExpiredInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventMatchExpired(msg.publish_subscribe_id, + msg.requestor_instance_id).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_followup = [weak_ptr_this]( + const legacy_hal::NanFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanFollowupReceivedInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventFollowupReceived(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_transmit_follow_up = [weak_ptr_this]( + const legacy_hal::NanTransmitFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason), + &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventTransmitFollowup(msg.id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_request = [weak_ptr_this]( + const legacy_hal::NanDataPathRequestInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanDataPathRequestInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDataPathRequest(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_confirm = [weak_ptr_this]( + const legacy_hal::NanDataPathConfirmInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanDataPathConfirmInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDataPathConfirm(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_end = [weak_ptr_this]( + const legacy_hal::NanDataPathEndInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + for (int i = 0; i < msg.num_ndp_instances; ++i) { + if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + } + }; + + callback_handlers.on_event_beacon_sdf_payload = [weak_ptr_this]( + const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) { + LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called"; + }; + + callback_handlers.on_event_range_request = [weak_ptr_this]( + const legacy_hal::NanRangeRequestInd& /* msg */) { + LOG(ERROR) << "on_event_range_request - should not be called"; + }; + + callback_handlers.on_event_range_report = [weak_ptr_this]( + const legacy_hal::NanRangeReportInd& /* msg */) { + LOG(ERROR) << "on_event_range_report - should not be called"; + }; + + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanRegisterCallbackHandlers(callback_handlers); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to register nan callbacks. Invalidating object"; + invalidate(); + } +} + +void WifiNanIface::invalidate() { + // send commands to HAL to actually disable and destroy interfaces + legacy_hal_.lock()->nanDisableRequest(0xFFFF); + legacy_hal_.lock()->nanDataInterfaceDelete(0xFFFE, "aware_data0"); + legacy_hal_.lock()->nanDataInterfaceDelete(0xFFFD, "aware_data1"); + + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiNanIface::isValid() { + return is_valid_; +} + +std::set> WifiNanIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return WifiNanIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getNameInternal, + hidl_status_cb); +} + +Return WifiNanIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getTypeInternal, + hidl_status_cb); +} + +Return WifiNanIface::registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallbackInternal, + hidl_status_cb, + callback); +} + +Return WifiNanIface::getCapabilitiesRequest(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequestInternal, + hidl_status_cb, + cmd_id); +} + +Return WifiNanIface::enableRequest(uint16_t cmd_id, + const NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::configRequest(uint16_t cmd_id, + const NanConfigRequest& msg, + configRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::disableRequest(uint16_t cmd_id, + disableRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::disableRequestInternal, + hidl_status_cb, + cmd_id); +} + +Return WifiNanIface::startPublishRequest(uint16_t cmd_id, + const NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::stopPublishRequest( + uint16_t cmd_id, + uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopPublishRequestInternal, + hidl_status_cb, + cmd_id, + sessionId); +} + +Return WifiNanIface::startSubscribeRequest( + uint16_t cmd_id, + const NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startSubscribeRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::stopSubscribeRequest( + uint16_t cmd_id, + uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopSubscribeRequestInternal, + hidl_status_cb, + cmd_id, + sessionId); +} + +Return WifiNanIface::transmitFollowupRequest( + uint16_t cmd_id, + const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::transmitFollowupRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::createDataInterfaceRequest( + uint16_t cmd_id, + const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::createDataInterfaceRequestInternal, + hidl_status_cb, + cmd_id, + iface_name); +} + +Return WifiNanIface::deleteDataInterfaceRequest( + uint16_t cmd_id, + const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::deleteDataInterfaceRequestInternal, + hidl_status_cb, + cmd_id, + iface_name); +} + +Return WifiNanIface::initiateDataPathRequest( + uint16_t cmd_id, + const NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::respondToDataPathIndicationRequest( + uint16_t cmd_id, + const NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequestInternal, + hidl_status_cb, + cmd_id, + msg); +} + +Return WifiNanIface::terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::terminateDataPathRequestInternal, + hidl_status_cb, + cmd_id, + ndpInstanceId); +} + +std::pair WifiNanIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiNanIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN}; +} + +WifiStatus WifiNanIface::registerEventCallbackInternal( + const sp& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanGetCapabilities(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::enableRequestInternal(uint16_t cmd_id, + const NanEnableRequest& msg) { + legacy_hal::NanEnableRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanEnableRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::configRequestInternal( + uint16_t cmd_id, const NanConfigRequest& msg) { + legacy_hal::NanConfigRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanConfigRequestToLegacy(msg, + &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanConfigRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDisableRequest(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t cmd_id, + const NanPublishRequest& msg) { + legacy_hal::NanPublishRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg, + &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::stopPublishRequestInternal( + uint16_t cmd_id, uint8_t sessionId) { + legacy_hal::NanPublishCancelRequest legacy_msg; + legacy_msg.publish_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishCancelRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startSubscribeRequestInternal( + uint16_t cmd_id, const NanSubscribeRequest& msg) { + legacy_hal::NanSubscribeRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg, + &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::stopSubscribeRequestInternal( + uint16_t cmd_id, uint8_t sessionId) { + legacy_hal::NanSubscribeCancelRequest legacy_msg; + legacy_msg.subscribe_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeCancelRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::transmitFollowupRequestInternal( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg) { + legacy_hal::NanTransmitFollowupRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanTransmitFollowupRequest(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::createDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceCreate(cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceDelete(cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::initiateDataPathRequestInternal( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg) { + legacy_hal::NanDataPathInitiatorRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataRequestInitiator(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) { + legacy_hal::NanDataPathIndicationResponse legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataIndicationResponse(cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::terminateDataPathRequestInternal( + uint16_t cmd_id, uint32_t ndpInstanceId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataEnd(cmd_id, ndpInstanceId); + return createWifiStatusFromLegacyError(legacy_status); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_nan_iface.h b/wifi/1.1/default/wifi_nan_iface.h new file mode 100644 index 000000000..260d8ab4e --- /dev/null +++ b/wifi/1.1/default/wifi_nan_iface.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_NAN_IFACE_H_ +#define WIFI_NAN_IFACE_H_ + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a NAN Iface instance. + */ +class WifiNanIface : public V1_0::IWifiNanIface { + public: + WifiNanIface(const std::string& ifname, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilitiesRequest(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) override; + Return enableRequest(uint16_t cmd_id, + const NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) override; + Return configRequest(uint16_t cmd_id, + const NanConfigRequest& msg, + configRequest_cb hidl_status_cb) override; + Return disableRequest(uint16_t cmd_id, + disableRequest_cb hidl_status_cb) override; + Return startPublishRequest(uint16_t cmd_id, + const NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + Return stopPublishRequest(uint16_t cmd_id, + uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) override; + Return startSubscribeRequest(uint16_t cmd_id, + const NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) override; + Return stopSubscribeRequest(uint16_t cmd_id, + uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) override; + Return transmitFollowupRequest(uint16_t cmd_id, + const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) override; + Return createDataInterfaceRequest(uint16_t cmd_id, + const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) override; + Return deleteDataInterfaceRequest(uint16_t cmd_id, + const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) override; + Return initiateDataPathRequest(uint16_t cmd_id, + const NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) override; + Return respondToDataPathIndicationRequest( + uint16_t cmd_id, + const NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) override; + Return terminateDataPathRequest(uint16_t cmd_id, + uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus registerEventCallbackInternal( + const sp& callback); + WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id); + WifiStatus enableRequestInternal(uint16_t cmd_id, + const NanEnableRequest& msg); + WifiStatus configRequestInternal(uint16_t cmd_id, + const NanConfigRequest& msg); + WifiStatus disableRequestInternal(uint16_t cmd_id); + WifiStatus startPublishRequestInternal(uint16_t cmd_id, + const NanPublishRequest& msg); + WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, + const NanSubscribeRequest& msg); + WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus transmitFollowupRequestInternal( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg); + WifiStatus createDataInterfaceRequestInternal(uint16_t cmd_id, + const std::string& iface_name); + WifiStatus deleteDataInterfaceRequestInternal(uint16_t cmd_id, + const std::string& iface_name); + WifiStatus initiateDataPathRequestInternal( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg); + WifiStatus terminateDataPathRequestInternal( + uint16_t cmd_id, uint32_t ndpInstanceId); + + std::set> getEventCallbacks(); + + std::string ifname_; + std::weak_ptr legacy_hal_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiNanIface); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_NAN_IFACE_H_ diff --git a/wifi/1.1/default/wifi_p2p_iface.cpp b/wifi/1.1/default/wifi_p2p_iface.cpp new file mode 100644 index 000000000..78e08db97 --- /dev/null +++ b/wifi/1.1/default/wifi_p2p_iface.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "wifi_p2p_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiP2pIface::WifiP2pIface( + const std::string& ifname, + const std::weak_ptr legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiP2pIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiP2pIface::isValid() { + return is_valid_; +} + +Return WifiP2pIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getNameInternal, + hidl_status_cb); +} + +Return WifiP2pIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getTypeInternal, + hidl_status_cb); +} + +std::pair WifiP2pIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiP2pIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P}; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_p2p_iface.h b/wifi/1.1/default/wifi_p2p_iface.h new file mode 100644 index 000000000..f563a3d31 --- /dev/null +++ b/wifi/1.1/default/wifi_p2p_iface.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_P2P_IFACE_H_ +#define WIFI_P2P_IFACE_H_ + +#include +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a P2P Iface instance. + */ +class WifiP2pIface : public V1_0::IWifiP2pIface { + public: + WifiP2pIface(const std::string& ifname, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + + std::string ifname_; + std::weak_ptr legacy_hal_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiP2pIface); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_P2P_IFACE_H_ diff --git a/wifi/1.1/default/wifi_rtt_controller.cpp b/wifi/1.1/default/wifi_rtt_controller.cpp new file mode 100644 index 000000000..9ef702da1 --- /dev/null +++ b/wifi/1.1/default/wifi_rtt_controller.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_rtt_controller.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiRttController::WifiRttController( + const sp& bound_iface, + const std::weak_ptr legacy_hal) + : bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiRttController::invalidate() { + legacy_hal_.reset(); + event_callbacks_.clear(); + is_valid_ = false; +} + +bool WifiRttController::isValid() { + return is_valid_; +} + +std::vector> +WifiRttController::getEventCallbacks() { + return event_callbacks_; +} + +Return WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getBoundIfaceInternal, + hidl_status_cb); +} + +Return WifiRttController::registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal, + hidl_status_cb, + callback); +} + +Return WifiRttController::rangeRequest( + uint32_t cmd_id, + const hidl_vec& rtt_configs, + rangeRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal, + hidl_status_cb, + cmd_id, + rtt_configs); +} + +Return WifiRttController::rangeCancel( + uint32_t cmd_id, + const hidl_vec>& addrs, + rangeCancel_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeCancelInternal, + hidl_status_cb, + cmd_id, + addrs); +} + +Return WifiRttController::getCapabilities( + getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiRttController::setLci(uint32_t cmd_id, + const RttLciInformation& lci, + setLci_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLciInternal, + hidl_status_cb, + cmd_id, + lci); +} + +Return WifiRttController::setLcr(uint32_t cmd_id, + const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLcrInternal, + hidl_status_cb, + cmd_id, + lcr); +} + +Return WifiRttController::getResponderInfo( + getResponderInfo_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal, + hidl_status_cb); +} + +Return WifiRttController::enableResponder( + uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info, + enableResponder_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal, + hidl_status_cb, + cmd_id, + channel_hint, + max_duration_seconds, + info); +} + +Return WifiRttController::disableResponder( + uint32_t cmd_id, disableResponder_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::disableResponderInternal, + hidl_status_cb, + cmd_id); +} + +std::pair> +WifiRttController::getBoundIfaceInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal( + const sp& callback) { + // TODO(b/31632518): remove the callback when the client is destroyed + event_callbacks_.emplace_back(callback); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiRttController::rangeRequestInternal( + uint32_t cmd_id, const std::vector& rtt_configs) { + std::vector legacy_configs; + if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy( + rtt_configs, &legacy_configs)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp weak_ptr_this(this); + const auto& on_results_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const std::vector& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector hidl_results; + if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl( + results, &hidl_results)) { + LOG(ERROR) << "Failed to convert rtt results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + callback->onResults(id, hidl_results); + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRttRangeRequest( + cmd_id, legacy_configs, on_results_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::rangeCancelInternal( + uint32_t cmd_id, const std::vector>& addrs) { + std::vector> legacy_addrs; + for (const auto& addr : addrs) { + legacy_addrs.push_back(addr); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->cancelRttRangeRequest(cmd_id, legacy_addrs); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiRttController::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getRttCapabilities(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + RttCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id, + const RttLciInformation& lci) { + legacy_hal::wifi_lci_information legacy_lci; + if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci, + &legacy_lci)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLci(cmd_id, legacy_lci); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id, + const RttLcrInformation& lcr) { + legacy_hal::wifi_lcr_information legacy_lcr; + if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr, + &legacy_lcr)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLcr(cmd_id, legacy_lcr); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiRttController::getResponderInfoInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_responder legacy_responder; + std::tie(legacy_status, legacy_responder) = + legacy_hal_.lock()->getRttResponderInfo(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + RttResponder hidl_responder; + if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, + &hidl_responder)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder}; +} + +WifiStatus WifiRttController::enableResponderInternal( + uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info) { + legacy_hal::wifi_channel_info legacy_channel_info; + if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy( + channel_hint, &legacy_channel_info)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_rtt_responder legacy_responder; + if (!hidl_struct_util::convertHidlRttResponderToLegacy(info, + &legacy_responder)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder( + cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->disableRttResponder(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_rtt_controller.h b/wifi/1.1/default/wifi_rtt_controller.h new file mode 100644 index 000000000..543788574 --- /dev/null +++ b/wifi/1.1/default/wifi_rtt_controller.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_RTT_CONTROLLER_H_ +#define WIFI_RTT_CONTROLLER_H_ + +#include +#include +#include +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { + +/** + * HIDL interface object used to control all RTT operations. + */ +class WifiRttController : public V1_0::IWifiRttController { + public: + WifiRttController(const sp& bound_iface, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::vector> getEventCallbacks(); + + // HIDL methods exposed. + Return getBoundIface(getBoundIface_cb hidl_status_cb) override; + Return registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return rangeRequest(uint32_t cmd_id, + const hidl_vec& rtt_configs, + rangeRequest_cb hidl_status_cb) override; + Return rangeCancel(uint32_t cmd_id, + const hidl_vec>& addrs, + rangeCancel_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return setLci(uint32_t cmd_id, + const RttLciInformation& lci, + setLci_cb hidl_status_cb) override; + Return setLcr(uint32_t cmd_id, + const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) override; + Return getResponderInfo(getResponderInfo_cb hidl_status_cb) override; + Return enableResponder(uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info, + enableResponder_cb hidl_status_cb) override; + Return disableResponder(uint32_t cmd_id, + disableResponder_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair> getBoundIfaceInternal(); + WifiStatus registerEventCallbackInternal( + const sp& callback); + WifiStatus rangeRequestInternal(uint32_t cmd_id, + const std::vector& rtt_configs); + WifiStatus rangeCancelInternal( + uint32_t cmd_id, const std::vector>& addrs); + std::pair getCapabilitiesInternal(); + WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci); + WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr); + std::pair getResponderInfoInternal(); + WifiStatus enableResponderInternal(uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info); + WifiStatus disableResponderInternal(uint32_t cmd_id); + + sp bound_iface_; + std::weak_ptr legacy_hal_; + std::vector> event_callbacks_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiRttController); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_RTT_CONTROLLER_H_ diff --git a/wifi/1.1/default/wifi_sta_iface.cpp b/wifi/1.1/default/wifi_sta_iface.cpp new file mode 100644 index 000000000..28f3f02a2 --- /dev/null +++ b/wifi/1.1/default/wifi_sta_iface.cpp @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2016 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 + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_sta_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiStaIface::WifiStaIface( + const std::string& ifname, + const std::weak_ptr legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) { + // Turn on DFS channel usage for STA iface. + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setDfsFlag(true); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable."; + } +} + +void WifiStaIface::invalidate() { + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiStaIface::isValid() { + return is_valid_; +} + +std::set> WifiStaIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return WifiStaIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getNameInternal, + hidl_status_cb); +} + +Return WifiStaIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getTypeInternal, + hidl_status_cb); +} + +Return WifiStaIface::registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::registerEventCallbackInternal, + hidl_status_cb, + callback); +} + +Return WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiStaIface::getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getApfPacketFilterCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiStaIface::installApfPacketFilter( + uint32_t cmd_id, + const hidl_vec& program, + installApfPacketFilter_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::installApfPacketFilterInternal, + hidl_status_cb, + cmd_id, + program); +} + +Return WifiStaIface::getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getBackgroundScanCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiStaIface::getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getValidFrequenciesForBandInternal, + hidl_status_cb, + band); +} + +Return WifiStaIface::startBackgroundScan( + uint32_t cmd_id, + const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startBackgroundScanInternal, + hidl_status_cb, + cmd_id, + params); +} + +Return WifiStaIface::stopBackgroundScan( + uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopBackgroundScanInternal, + hidl_status_cb, + cmd_id); +} + +Return WifiStaIface::enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableLinkLayerStatsCollectionInternal, + hidl_status_cb, + debug); +} + +Return WifiStaIface::disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::disableLinkLayerStatsCollectionInternal, + hidl_status_cb); +} + +Return WifiStaIface::getLinkLayerStats( + getLinkLayerStats_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal, + hidl_status_cb); +} + +Return WifiStaIface::startRssiMonitoring( + uint32_t cmd_id, + int32_t max_rssi, + int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startRssiMonitoringInternal, + hidl_status_cb, + cmd_id, + max_rssi, + min_rssi); +} + +Return WifiStaIface::stopRssiMonitoring( + uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopRssiMonitoringInternal, + hidl_status_cb, + cmd_id); +} + +Return WifiStaIface::getRoamingCapabilities( + getRoamingCapabilities_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getRoamingCapabilitiesInternal, + hidl_status_cb); +} + +Return WifiStaIface::configureRoaming( + const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::configureRoamingInternal, + hidl_status_cb, + config); +} + +Return WifiStaIface::setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setRoamingStateInternal, + hidl_status_cb, + state); +} + +Return WifiStaIface::enableNdOffload(bool enable, + enableNdOffload_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableNdOffloadInternal, + hidl_status_cb, + enable); +} + +Return WifiStaIface::startSendingKeepAlivePackets( + uint32_t cmd_id, + const hidl_vec& ip_packet_data, + uint16_t ether_type, + const hidl_array& src_address, + const hidl_array& dst_address, + uint32_t period_in_ms, + startSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startSendingKeepAlivePacketsInternal, + hidl_status_cb, + cmd_id, + ip_packet_data, + ether_type, + src_address, + dst_address, + period_in_ms); +} + +Return WifiStaIface::stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopSendingKeepAlivePacketsInternal, + hidl_status_cb, + cmd_id); +} + +Return WifiStaIface::setScanningMacOui( + const hidl_array& oui, setScanningMacOui_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanningMacOuiInternal, + hidl_status_cb, + oui); +} + +Return WifiStaIface::startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startDebugPacketFateMonitoringInternal, + hidl_status_cb); +} + +Return WifiStaIface::getDebugTxPacketFates( + getDebugTxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugTxPacketFatesInternal, + hidl_status_cb); +} + +Return WifiStaIface::getDebugRxPacketFates( + getDebugRxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugRxPacketFatesInternal, + hidl_status_cb); +} + +std::pair WifiStaIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiStaIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA}; +} + +WifiStatus WifiStaIface::registerEventCallbackInternal( + const sp& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair WifiStaIface::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + uint32_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + uint32_t legacy_logger_feature_set; + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // some devices don't support querying logger feature set + legacy_logger_feature_set = 0; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair +WifiStaIface::getApfPacketFilterCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::PacketFilterCapabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getPacketFilterCapabilities(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaApfPacketFilterCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::installApfPacketFilterInternal( + uint32_t /* cmd_id */, const std::vector& program) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setPacketFilter(program); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiStaIface::getBackgroundScanCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_gscan_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getGscanCapabilities(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaBackgroundScanCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair> +WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector valid_frequencies; + std::tie(legacy_status, valid_frequencies) = + legacy_hal_.lock()->getValidFrequenciesForBand( + hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} + +WifiStatus WifiStaIface::startBackgroundScanInternal( + uint32_t cmd_id, const StaBackgroundScanParameters& params) { + legacy_hal::wifi_scan_cmd_params legacy_params; + if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params, + &legacy_params)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp weak_ptr_this(this); + const auto& on_failure_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanFailure(id).isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback"; + } + } + }; + const auto& on_results_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const std::vector& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector hidl_scan_datas; + if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl( + results, &hidl_scan_datas)) { + LOG(ERROR) << "Failed to convert scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanResults(id, hidl_scan_datas).isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback"; + } + } + }; + const auto& on_full_result_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const legacy_hal::wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + StaScanResult hidl_scan_result; + if (!hidl_struct_util::convertLegacyGscanResultToHidl( + *result, true, &hidl_scan_result)) { + LOG(ERROR) << "Failed to convert full scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundFullScanResult( + id, buckets_scanned, hidl_scan_result).isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startGscan(cmd_id, + legacy_params, + on_failure_callback, + on_results_callback, + on_full_result_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->enableLinkLayerStats(debug); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->disableLinkLayerStats(); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiStaIface::getLinkLayerStatsInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::LinkLayerStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getLinkLayerStats(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaLinkLayerStats hidl_stats; + if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, + &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id, + int32_t max_rssi, + int32_t min_rssi) { + android::wp weak_ptr_this(this); + const auto& on_threshold_breached_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + std::array bssid, + int8_t rssi) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) { + LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRssiMonitoring( + cmd_id, max_rssi, min_rssi, on_threshold_breached_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopRssiMonitoring(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiStaIface::getRoamingCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_roaming_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getRoamingCapabilities(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaRoamingCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::configureRoamingInternal( + const StaRoamingConfig& config) { + legacy_hal::wifi_roaming_config legacy_config; + if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config, + &legacy_config)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->configureRoaming(legacy_config); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->enableFirmwareRoaming( + hidl_struct_util::convertHidlRoamingStateToLegacy(state)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->configureNdOffload(enable); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, + const std::vector& ip_packet_data, + uint16_t /* ether_type */, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startSendingOffloadedPacket( + cmd_id, ip_packet_data, src_address, dst_address, period_in_ms); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopSendingOffloadedPacket(cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setScanningMacOuiInternal( + const std::array& oui) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setScanningMacOui(oui); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startPktFateMonitoring(); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> +WifiStaIface::getDebugTxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl( + legacy_fates, &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +std::pair> +WifiStaIface::getDebugRxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl( + legacy_fates, &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_sta_iface.h b/wifi/1.1/default/wifi_sta_iface.h new file mode 100644 index 000000000..587a5de7b --- /dev/null +++ b/wifi/1.1/default/wifi_sta_iface.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_STA_IFACE_H_ +#define WIFI_STA_IFACE_H_ + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a STA Iface instance. + */ +class WifiStaIface : public V1_0::IWifiStaIface { + public: + WifiStaIface(const std::string& ifname, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::set> getEventCallbacks(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) override; + Return installApfPacketFilter( + uint32_t cmd_id, + const hidl_vec& program, + installApfPacketFilter_cb hidl_status_cb) override; + Return getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) override; + Return getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override; + Return startBackgroundScan( + uint32_t cmd_id, + const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) override; + Return stopBackgroundScan( + uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override; + Return enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override; + Return startRssiMonitoring( + uint32_t cmd_id, + int32_t max_rssi, + int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) override; + Return stopRssiMonitoring( + uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override; + Return getRoamingCapabilities( + getRoamingCapabilities_cb hidl_status_cb) override; + Return configureRoaming(const StaRoamingConfig& config, + configureRoaming_cb hidl_status_cb) override; + Return setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) override; + Return enableNdOffload(bool enable, + enableNdOffload_cb hidl_status_cb) override; + Return startSendingKeepAlivePackets( + uint32_t cmd_id, + const hidl_vec& ip_packet_data, + uint16_t ether_type, + const hidl_array& src_address, + const hidl_array& dst_address, + uint32_t period_in_ms, + startSendingKeepAlivePackets_cb hidl_status_cb) override; + Return stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override; + Return setScanningMacOui(const hidl_array& oui, + setScanningMacOui_cb hidl_status_cb) override; + Return startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) override; + Return getDebugTxPacketFates( + getDebugTxPacketFates_cb hidl_status_cb) override; + Return getDebugRxPacketFates( + getDebugRxPacketFates_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus registerEventCallbackInternal( + const sp& callback); + std::pair getCapabilitiesInternal(); + std::pair + getApfPacketFilterCapabilitiesInternal(); + WifiStatus installApfPacketFilterInternal( + uint32_t cmd_id, const std::vector& program); + std::pair + getBackgroundScanCapabilitiesInternal(); + std::pair> + getValidFrequenciesForBandInternal(WifiBand band); + WifiStatus startBackgroundScanInternal( + uint32_t cmd_id, const StaBackgroundScanParameters& params); + WifiStatus stopBackgroundScanInternal(uint32_t cmd_id); + WifiStatus enableLinkLayerStatsCollectionInternal(bool debug); + WifiStatus disableLinkLayerStatsCollectionInternal(); + std::pair getLinkLayerStatsInternal(); + WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, + int32_t max_rssi, + int32_t min_rssi); + WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); + std::pair + getRoamingCapabilitiesInternal(); + WifiStatus configureRoamingInternal(const StaRoamingConfig& config); + WifiStatus setRoamingStateInternal(StaRoamingState state); + WifiStatus enableNdOffloadInternal(bool enable); + WifiStatus startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, + const std::vector& ip_packet_data, + uint16_t ether_type, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms); + WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id); + WifiStatus setScanningMacOuiInternal(const std::array& oui); + WifiStatus startDebugPacketFateMonitoringInternal(); + std::pair> + getDebugTxPacketFatesInternal(); + std::pair> + getDebugRxPacketFatesInternal(); + + std::string ifname_; + std::weak_ptr legacy_hal_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiStaIface); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STA_IFACE_H_ diff --git a/wifi/1.1/default/wifi_status_util.cpp b/wifi/1.1/default/wifi_status_util.cpp new file mode 100644 index 000000000..3a85e0998 --- /dev/null +++ b/wifi/1.1/default/wifi_status_util.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2016 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 "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { + +std::string legacyErrorToString(legacy_hal::wifi_error error) { + switch (error) { + case legacy_hal::WIFI_SUCCESS: + return "SUCCESS"; + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + return "UNINITIALIZED"; + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return "NOT_AVAILABLE"; + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return "NOT_SUPPORTED"; + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + return "INVALID_ARGS"; + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return "INVALID_REQUEST_ID"; + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return "TIMED_OUT"; + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return "TOO_MANY_REQUESTS"; + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case legacy_hal::WIFI_ERROR_BUSY: + return "BUSY"; + case legacy_hal::WIFI_ERROR_UNKNOWN: + return "UNKNOWN"; + } +} + +WifiStatus createWifiStatus(WifiStatusCode code, + const std::string& description) { + return {code, description}; +} + +WifiStatus createWifiStatus(WifiStatusCode code) { + return createWifiStatus(code, ""); +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, + const std::string& desc) { + switch (error) { + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc); + + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc); + + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc); + + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", timed out"); + + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", too many requests"); + + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", out of memory"); + + case legacy_hal::WIFI_ERROR_BUSY: + return createWifiStatus(WifiStatusCode::ERROR_BUSY); + + case legacy_hal::WIFI_ERROR_NONE: + return createWifiStatus(WifiStatusCode::SUCCESS, desc); + + case legacy_hal::WIFI_ERROR_UNKNOWN: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown"); + } +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { + return createWifiStatusFromLegacyError(error, ""); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.1/default/wifi_status_util.h b/wifi/1.1/default/wifi_status_util.h new file mode 100644 index 000000000..cc93d66ca --- /dev/null +++ b/wifi/1.1/default/wifi_status_util.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef WIFI_STATUS_UTIL_H_ +#define WIFI_STATUS_UTIL_H_ + +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_1 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +std::string legacyErrorToString(legacy_hal::wifi_error error); +WifiStatus createWifiStatus(WifiStatusCode code, + const std::string& description); +WifiStatus createWifiStatus(WifiStatusCode code); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, + const std::string& description); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error); + +} // namespace implementation +} // namespace V1_1 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STATUS_UTIL_H_ diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp new file mode 100644 index 000000000..6b0baf785 --- /dev/null +++ b/wifi/1.1/vts/functional/Android.bp @@ -0,0 +1,39 @@ +// +// Copyright (C) 2016 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. +// + +cc_test { + name: "VtsHalWifiV1_1TargetTest", + defaults: ["hidl_defaults"], + srcs: [ + "VtsHalWifiV1_1TargetTest.cpp", + "wifi_chip_hidl_test.cpp"], + shared_libs: [ + "libbase", + "liblog", + "libcutils", + "libhidlbase", + "libhidltransport", + "libnativehelper", + "libutils", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + ], + static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"], + cflags: [ + "-O0", + "-g", + ], +} diff --git a/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp new file mode 100644 index 000000000..160fcd234 --- /dev/null +++ b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 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 + +#include + +#include "wifi_hidl_test_utils.h" + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(new WifiHidlEnvironment); + ::testing::InitGoogleTest(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} diff --git a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp new file mode 100644 index 000000000..839b6c434 --- /dev/null +++ b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 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 + +#include +#include + +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::wifi::V1_0::IfaceType; +using ::android::hardware::wifi::V1_0::ChipId; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::WifiStatus; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_1::IWifi; +using ::android::hardware::wifi::V1_1::IWifiChip; +using ::android::hardware::wifi::V1_0::IWifiStaIface; + +namespace { +constexpr int32_t kFakePowerInDbm = -56; +}; //namespace + +/** + * Fixture to use for all Wifi chip HIDL interface tests. + */ +class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + wifi_chip_ = IWifiChip::castFrom(getWifiChip()); + ASSERT_NE(nullptr, wifi_chip_.get()); + } + + virtual void TearDown() override { stopWifi(); } + + protected: + uint32_t configureChipForStaIfaceAndGetCapabilities() { + ChipModeId mode_id; + EXPECT_TRUE(configureChipToSupportIfaceType( + wifi_chip_, IfaceType::STA, &mode_id)); + const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); + return status_and_caps.second; + } + + sp wifi_chip_; +}; + +/* + * SetTxPowerLimit + */ +TEST_F(WifiChipHidlTest, SetTxPowerLimit) { + uint32_t caps = configureChipForStaIfaceAndGetCapabilities(); + const auto& status = + HIDL_INVOKE(wifi_chip_, setTxPowerLimit, kFakePowerInDbm); + if (caps & IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT) { + EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); + } else { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code); + } +} + +/* + * SetTxPowerLimit + */ +TEST_F(WifiChipHidlTest, ResetTxPowerLimit) { + uint32_t caps = configureChipForStaIfaceAndGetCapabilities(); + const auto& status = + HIDL_INVOKE(wifi_chip_, resetTxPowerLimit); + if (caps & IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT) { + EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); + } else { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code); + } +} -- cgit v1.2.3