diff options
Diffstat (limited to 'wifi')
63 files changed, 21139 insertions, 0 deletions
diff --git a/wifi/wifi_legacy_service/1.0-legacy/Android.bp b/wifi/wifi_legacy_service/1.0-legacy/Android.bp new file mode 100644 index 0000000..0d0dfdf --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/Android.bp @@ -0,0 +1,182 @@ +// Copyright (C) 2021 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. + +soong_config_module_type { + name: "wifi_hal_cc_defaults", + module_type: "cc_defaults", + config_namespace: "wifi", + bool_variables: [ + "hidl_feature_aware", // WIFI_HIDL_FEATURE_AWARE + "hidl_feature_dual_interface", // WIFI_HIDL_FEATURE_DUAL_INTERFACE + "hidl_feature_disable_ap", // WIFI_HIDL_FEATURE_DISABLE_AP + "hidl_feature_disable_ap_mac_randomization", // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION + "avoid_iface_reset_mac_change", // WIFI_AVOID_IFACE_RESET_MAC_CHANGE + "wifi_skip_state_toggle_off_on_for_nan", // WIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN + ], + value_variables: [ + "hal_interface_combinations", // WIFI_HAL_INTERFACE_COMBINATIONS + ], + properties: [ + "cppflags", + ], +} + +wifi_hal_cc_defaults { + name: "android.hardware.wifi@1.0-service.legacy-cppflags-defaults", + soong_config_variables: { + hidl_feature_aware: { + cppflags: ["-DWIFI_HIDL_FEATURE_AWARE"], + }, + hidl_feature_dual_interface: { + cppflags: ["-DWIFI_HIDL_FEATURE_DUAL_INTERFACE"], + }, + hidl_feature_disable_ap: { + cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP"], + }, + hidl_feature_disable_ap_mac_randomization: { + cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION"], + }, + avoid_iface_reset_mac_change: { + cppflags: ["-DWIFI_AVOID_IFACE_RESET_MAC_CHANGE"], + }, + wifi_skip_state_toggle_off_on_for_nan: { + cppflags: ["-DWIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN"], + }, + hal_interface_combinations: { + cppflags: ["-DWIFI_HAL_INTERFACE_COMBINATIONS=%s"], + }, + }, +} + +cc_library_static { + name: "android.hardware.wifi@1.0-service.legacy-lib", + defaults: ["android.hardware.wifi@1.0-service.legacy-cppflags-defaults"], + proprietary: true, + compile_multilib: "first", + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + // Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed. + cflags: ["-Wno-error=implicit-fallthrough"], + srcs: [ + "hidl_struct_util.cpp", + "hidl_sync_util.cpp", + "ringbuffer.cpp", + "wifi.cpp", + "wifi_ap_iface.cpp", + "wifi_chip.cpp", + "wifi_feature_flags.cpp", + "wifi_iface_util.cpp", + "wifi_legacy_hal.cpp", + "wifi_legacy_hal_factory.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", + ], + + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + + export_include_dirs: ["."], +} + +cc_binary { + name: "android.hardware.wifi@1.0-service.legacy", + vintf_fragments: ["android.hardware.wifi@1.0-service.legacy.xml"], + relative_install_path: "hw", + proprietary: true, + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + srcs: ["service.cpp"], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + static_libs: ["android.hardware.wifi@1.0-service.legacy-lib"], + init_rc: ["android.hardware.wifi@1.0-service.legacy.rc"], +} + +cc_binary { + name: "android.hardware.wifi@1.0-service.legacy-lazy", + vintf_fragments: ["android.hardware.wifi@1.0-service.legacy.xml"], + overrides: ["android.hardware.wifi@1.0-service.legacy"], + cflags: ["-DLAZY_SERVICE"], + relative_install_path: "hw", + proprietary: true, + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + srcs: ["service.cpp"], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + static_libs: ["android.hardware.wifi@1.0-service.legacy-lib"], + init_rc: ["android.hardware.wifi@1.0-service.legacy-lazy.rc"], +} diff --git a/wifi/wifi_legacy_service/1.0-legacy/THREADING.README b/wifi/wifi_legacy_service/1.0-legacy/THREADING.README new file mode 100644 index 0000000..8366ca0 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/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/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc new file mode 100644 index 0000000..5bf3223 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc @@ -0,0 +1,14 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service.legacy-lazy + interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default + interface android.hardware.wifi@1.6::IWifi default + oneshot + disabled + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc new file mode 100644 index 0000000..fb18f68 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc @@ -0,0 +1,12 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service.legacy + interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default + interface android.hardware.wifi@1.6::IWifi default + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml new file mode 100644 index 0000000..771fbaa --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.wifi</name> + <transport>hwbinder</transport> + <version>1.6</version> + <interface> + <name>IWifi</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h new file mode 100644 index 0000000..eb61472 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 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 ANDROID_AUDIO_HARDWARE_BASE_H +#define ANDROID_AUDIO_HARDWARE_BASE_H + +#include <hardware_legacy/AudioHardwareInterface.h> + +#include <system/audio.h> + +namespace android_audio_legacy { + +// ---------------------------------------------------------------------------- + +/** + * AudioHardwareBase is a convenient base class used for implementing the + * AudioHardwareInterface interface. + */ +class AudioHardwareBase : public AudioHardwareInterface { + public: + AudioHardwareBase(); + virtual ~AudioHardwareBase() {} + + /** + * setMode is called when the audio mode changes. NORMAL mode is for + * standard audio playback, RINGTONE when a ringtone is playing, IN_CALL + * when a telephony call is in progress, IN_COMMUNICATION when a VoIP call is in progress. + */ + virtual status_t setMode(int mode); + + virtual status_t setParameters(const String8& keyValuePairs); + virtual String8 getParameters(const String8& keys); + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); + virtual status_t getMasterVolume(float* volume); + + /**This method dumps the state of the audio hardware */ + virtual status_t dumpState(int fd, const Vector<String16>& args); + + protected: + /** returns true if the given mode maps to a telephony or VoIP call is in progress */ + virtual bool isModeInCall(int mode) { + return ((mode == AudioSystem::MODE_IN_CALL) || + (mode == AudioSystem::MODE_IN_COMMUNICATION)); + }; + /** returns true if a telephony or VoIP call is in progress */ + virtual bool isInCall() { return isModeInCall(mMode); }; + int mMode; +}; + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIO_HARDWARE_BASE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h new file mode 100644 index 0000000..7befb79 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2007 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 ANDROID_AUDIO_HARDWARE_INTERFACE_H +#define ANDROID_AUDIO_HARDWARE_INTERFACE_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/String16.h> +#include <utils/String8.h> +#include <utils/Vector.h> + +#include <hardware_legacy/AudioSystemLegacy.h> + +#include <hardware/audio.h> +#include <system/audio.h> + +#include <cutils/bitops.h> + +namespace android_audio_legacy { +using android::String16; +using android::String8; +using android::Vector; + +// ---------------------------------------------------------------------------- + +/** + * AudioStreamOut is the abstraction interface for the audio output hardware. + * + * It provides information about various properties of the audio output hardware driver. + */ +class AudioStreamOut { + public: + virtual ~AudioStreamOut() = 0; + + /** return audio sampling rate in hz - eg. 44100 */ + virtual uint32_t sampleRate() const = 0; + + /** returns size of output buffer - eg. 4800 */ + virtual size_t bufferSize() const = 0; + + /** + * returns the output channel mask + */ + virtual uint32_t channels() const = 0; + + /** + * return audio format in 8bit or 16bit PCM format - + * eg. AudioSystem:PCM_16_BIT + */ + virtual int format() const = 0; + + /** + * return the frame size (number of bytes per sample). + */ + uint32_t frameSize() const { + return audio_channel_count_from_out_mask(channels()) * + ((format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(int8_t)); + } + + /** + * return the audio hardware driver latency in milli seconds. + */ + virtual uint32_t latency() const = 0; + + /** + * Use this method in situations where audio mixing is done in the + * hardware. This method serves as a direct interface with hardware, + * allowing you to directly set the volume as apposed to via the framework. + * This method might produce multiple PCM outputs or hardware accelerated + * codecs, such as MP3 or AAC. + */ + virtual status_t setVolume(float left, float right) = 0; + + /** write audio buffer to driver. Returns number of bytes written */ + virtual ssize_t write(const void* buffer, size_t bytes) = 0; + + /** + * Put the audio hardware output into standby mode. Returns + * status based on include/utils/Errors.h + */ + virtual status_t standby() = 0; + + /** dump the state of the audio output device */ + virtual status_t dump(int fd, const Vector<String16>& args) = 0; + + // set/get audio output parameters. The function accepts a list of parameters + // key value pairs in the form: key1=value1;key2=value2;... + // Some keys are reserved for standard parameters (See AudioParameter class). + // If the implementation does not accept a parameter change while the output is + // active but the parameter is acceptable otherwise, it must return INVALID_OPERATION. + // The audio flinger will put the output in standby and then change the parameter value. + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // return the number of audio frames written by the audio dsp to DAC since + // the output has exited standby + virtual status_t getRenderPosition(uint32_t* dspFrames) = 0; + + /** + * get the local time at which the next write to the audio driver will be + * presented + */ + virtual status_t getNextWriteTimestamp(int64_t* timestamp); + + /** + * Return a recent count of the number of audio frames presented to an external observer. + */ + virtual status_t getPresentationPosition(uint64_t* frames, struct timespec* timestamp); +}; + +/** + * AudioStreamIn is the abstraction interface for the audio input hardware. + * + * It defines the various properties of the audio hardware input driver. + */ +class AudioStreamIn { + public: + virtual ~AudioStreamIn() = 0; + + /** return audio sampling rate in hz - eg. 44100 */ + virtual uint32_t sampleRate() const = 0; + + /** return the input buffer size allowed by audio driver */ + virtual size_t bufferSize() const = 0; + + /** return input channel mask */ + virtual uint32_t channels() const = 0; + + /** + * return audio format in 8bit or 16bit PCM format - + * eg. AudioSystem:PCM_16_BIT + */ + virtual int format() const = 0; + + /** + * return the frame size (number of bytes per sample). + */ + uint32_t frameSize() const { + return audio_channel_count_from_in_mask(channels()) * + ((format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(int8_t)); + } + + /** set the input gain for the audio driver. This method is for + * for future use */ + virtual status_t setGain(float gain) = 0; + + /** read audio buffer in from audio driver */ + virtual ssize_t read(void* buffer, ssize_t bytes) = 0; + + /** dump the state of the audio input device */ + virtual status_t dump(int fd, const Vector<String16>& args) = 0; + + /** + * Put the audio hardware input into standby mode. Returns + * status based on include/utils/Errors.h + */ + virtual status_t standby() = 0; + + // set/get audio input parameters. The function accepts a list of parameters + // key value pairs in the form: key1=value1;key2=value2;... + // Some keys are reserved for standard parameters (See AudioParameter class). + // If the implementation does not accept a parameter change while the output is + // active but the parameter is acceptable otherwise, it must return INVALID_OPERATION. + // The audio flinger will put the input in standby and then change the parameter value. + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // Return the number of input frames lost in the audio driver since the last call of this + // function. Audio driver is expected to reset the value to 0 and restart counting upon + // returning the current value by this function call. Such loss typically occurs when the user + // space process is blocked longer than the capacity of audio driver buffers. Unit: the number + // of input audio frames + virtual unsigned int getInputFramesLost() const = 0; + + virtual status_t addAudioEffect(effect_handle_t effect) = 0; + virtual status_t removeAudioEffect(effect_handle_t effect) = 0; +}; + +/** + * AudioHardwareInterface.h defines the interface to the audio hardware abstraction layer. + * + * The interface supports setting and getting parameters, selecting audio routing + * paths, and defining input and output streams. + * + * AudioFlinger initializes the audio hardware and immediately opens an output stream. + * You can set Audio routing to output to handset, speaker, Bluetooth, or a headset. + * + * The audio input stream is initialized when AudioFlinger is called to carry out + * a record operation. + */ +class AudioHardwareInterface { + public: + virtual ~AudioHardwareInterface() {} + + /** + * check to see if the audio hardware interface has been initialized. + * return status based on values defined in include/utils/Errors.h + */ + virtual status_t initCheck() = 0; + + /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */ + virtual status_t setVoiceVolume(float volume) = 0; + + /** + * set the audio volume for all audio activities other than voice call. + * Range between 0.0 and 1.0. If any value other than NO_ERROR is returned, + * the software mixer will emulate this capability. + */ + virtual status_t setMasterVolume(float volume) = 0; + + /** + * Get the current master volume value for the HAL, if the HAL supports + * master volume control. AudioFlinger will query this value from the + * primary audio HAL when the service starts and use the value for setting + * the initial master volume across all HALs. + */ + virtual status_t getMasterVolume(float* volume) = 0; + + /** + * setMode is called when the audio mode changes. NORMAL mode is for + * standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL + * when a call is in progress. + */ + virtual status_t setMode(int mode) = 0; + + // mic mute + virtual status_t setMicMute(bool state) = 0; + virtual status_t getMicMute(bool* state) = 0; + + // set/get global audio parameters + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // Returns audio input buffer size according to parameters passed or 0 if one of the + // parameters is not supported + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0; + + /** This method creates and opens the audio hardware output stream */ + virtual AudioStreamOut* openOutputStream(uint32_t devices, int* format = 0, + uint32_t* channels = 0, uint32_t* sampleRate = 0, + status_t* status = 0) = 0; + virtual AudioStreamOut* openOutputStreamWithFlags( + uint32_t devices, audio_output_flags_t flags = (audio_output_flags_t)0, int* format = 0, + uint32_t* channels = 0, uint32_t* sampleRate = 0, status_t* status = 0) = 0; + virtual void closeOutputStream(AudioStreamOut* out) = 0; + + /** This method creates and opens the audio hardware input stream */ + virtual AudioStreamIn* openInputStream(uint32_t devices, int* format, uint32_t* channels, + uint32_t* sampleRate, status_t* status, + AudioSystem::audio_in_acoustics acoustics) = 0; + virtual void closeInputStream(AudioStreamIn* in) = 0; + + /**This method dumps the state of the audio hardware */ + virtual status_t dumpState(int fd, const Vector<String16>& args) = 0; + + virtual status_t setMasterMute(bool muted) = 0; + + static AudioHardwareInterface* create(); + + virtual int createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources, + unsigned int num_sinks, const struct audio_port_config* sinks, + audio_patch_handle_t* handle) = 0; + + virtual int releaseAudioPatch(audio_patch_handle_t handle) = 0; + + virtual int getAudioPort(struct audio_port* port) = 0; + + virtual int setAudioPortConfig(const struct audio_port_config* config) = 0; + + protected: + virtual status_t dump(int fd, const Vector<String16>& args) = 0; +}; + +// ---------------------------------------------------------------------------- + +extern "C" AudioHardwareInterface* createAudioHardware(void); + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIO_HARDWARE_INTERFACE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h new file mode 100644 index 0000000..ec9c432 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2009 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 ANDROID_AUDIOPOLICYINTERFACE_H +#define ANDROID_AUDIOPOLICYINTERFACE_H + +#include <media/AudioSystem.h> +#include <media/ToneGenerator.h> +#include <utils/String8.h> + +#include <hardware/audio_policy.h> +#include <hardware_legacy/AudioSystemLegacy.h> + +namespace android_audio_legacy { +using android::String8; +using android::ToneGenerator; +using android::Vector; + +// ---------------------------------------------------------------------------- + +// The AudioPolicyInterface and AudioPolicyClientInterface classes define the communication +// interfaces between the platform specific audio policy manager and Android generic audio policy +// manager. The platform specific audio policy manager must implement methods of the +// AudioPolicyInterface class. This implementation makes use of the AudioPolicyClientInterface to +// control the activity and configuration of audio input and output streams. +// +// The platform specific audio policy manager is in charge of the audio routing and volume control +// policies for a given platform. +// The main roles of this module are: +// - keep track of current system state (removable device connections, phone state, user +// requests...). System state changes and user actions are notified to audio policy manager with +// methods of the AudioPolicyInterface. +// - process getOutput() queries received when AudioTrack objects are created: Those queries +// return a handler on an output that has been selected, configured and opened by the audio policy +// manager and that must be used by the AudioTrack when registering to the AudioFlinger with the +// createTrack() method. When the AudioTrack object is released, a putOutput() query is received +// and the audio policy manager can decide to close or reconfigure the output depending on other +// streams using this output and current system state. +// - similarly process getInput() and putInput() queries received from AudioRecord objects and +// configure audio inputs. +// - process volume control requests: the stream volume is converted from an index value (received +// from UI) to a float value applicable to each output as a function of platform specific settings +// and current output route (destination device). It also make sure that streams are not muted if +// not allowed (e.g. camera shutter sound in some countries). +// +// The platform specific audio policy manager is provided as a shared library by platform vendors +// (as for libaudio.so) and is linked with libaudioflinger.so + +// Audio Policy Manager Interface +class AudioPolicyInterface { + public: + virtual ~AudioPolicyInterface() {} + // + // configuration functions + // + + // indicate a change in device connection status + virtual status_t setDeviceConnectionState(audio_devices_t device, + AudioSystem::device_connection_state state, + const char* device_address) = 0; + // retrieve a device connection status + virtual AudioSystem::device_connection_state getDeviceConnectionState( + audio_devices_t device, const char* device_address) = 0; + // indicate a change in phone state. Valid phones states are defined by AudioSystem::audio_mode + virtual void setPhoneState(int state) = 0; + // force using a specific device category for the specified usage + virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) = 0; + // retrieve current device category forced for a given usage + virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage) = 0; + // set a system property (e.g. camera sound always audible) + virtual void setSystemProperty(const char* property, const char* value) = 0; + // check proper initialization + virtual status_t initCheck() = 0; + + // + // Audio routing query functions + // + + // request an output appropriate for playback of the supplied stream type and parameters + virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::output_flags flags, + const audio_offload_info_t* offloadInfo) = 0; + // indicates to the audio policy manager that the output starts being used by corresponding + // stream. + virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE) = 0; + // indicates to the audio policy manager that the output stops being used by corresponding + // stream. + virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE) = 0; + // releases the output. + virtual void releaseOutput(audio_io_handle_t output) = 0; + + // request an input appropriate for record from the supplied device with supplied parameters. + virtual audio_io_handle_t getInput(int inputSource, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::audio_in_acoustics acoustics) = 0; + // indicates to the audio policy manager that the input starts being used. + virtual status_t startInput(audio_io_handle_t input) = 0; + // indicates to the audio policy manager that the input stops being used. + virtual status_t stopInput(audio_io_handle_t input) = 0; + // releases the input. + virtual void releaseInput(audio_io_handle_t input) = 0; + + // + // volume control functions + // + + // initialises stream volume conversion parameters by specifying volume index range. + virtual void initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax) = 0; + + // sets the new stream volume at a level corresponding to the supplied index for the + // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // setting volume for all devices + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index, + audio_devices_t device) = 0; + + // retrieve current volume index for the specified stream and the + // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // querying the volume of the active device. + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int* index, + audio_devices_t device) = 0; + + // return the strategy corresponding to a given stream type + virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0; + + // return the enabled output devices for the given stream type + virtual audio_devices_t getDevicesForStream(AudioSystem::stream_type stream) = 0; + + // Audio effect management + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t* desc) = 0; + virtual status_t registerEffect(const effect_descriptor_t* desc, audio_io_handle_t io, + uint32_t strategy, audio_session_t session, int id) = 0; + virtual status_t unregisterEffect(int id) = 0; + virtual status_t setEffectEnabled(int id, bool enabled) = 0; + + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0; + virtual bool isStreamActiveRemotely(int stream, uint32_t inPastMs = 0) const = 0; + virtual bool isSourceActive(audio_source_t source) const = 0; + + // dump state + virtual status_t dump(int fd) = 0; + + virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0; +}; + +// Audio Policy client Interface +class AudioPolicyClientInterface { + public: + virtual ~AudioPolicyClientInterface() {} + + // + // Audio HW module functions + // + + // loads a HW module. + virtual audio_module_handle_t loadHwModule(const char* name) = 0; + + // + // Audio output Control functions + // + + // opens an audio output with the requested parameters. The parameter values can indicate to use + // the default values in case the audio policy manager has no specific requirements for the + // output being opened. When the function returns, the parameter values reflect the actual + // values used by the audio hardware output stream. The audio policy manager can check if the + // proposed parameters are suitable or not and act accordingly. + virtual audio_io_handle_t openOutput(audio_module_handle_t module, audio_devices_t* pDevices, + uint32_t* pSamplingRate, audio_format_t* pFormat, + audio_channel_mask_t* pChannelMask, uint32_t* pLatencyMs, + audio_output_flags_t flags, + const audio_offload_info_t* offloadInfo = NULL) = 0; + // creates a special output that is duplicated to the two outputs passed as arguments. The + // duplication is performed by a special mixer thread in the AudioFlinger. + virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, + audio_io_handle_t output2) = 0; + // closes the output stream + virtual status_t closeOutput(audio_io_handle_t output) = 0; + // suspends the output. When an output is suspended, the corresponding audio hardware output + // stream is placed in standby and the AudioTracks attached to the mixer thread are still + // processed but the output mix is discarded. + virtual status_t suspendOutput(audio_io_handle_t output) = 0; + // restores a suspended output. + virtual status_t restoreOutput(audio_io_handle_t output) = 0; + + // + // Audio input Control functions + // + + // opens an audio input + virtual audio_io_handle_t openInput(audio_module_handle_t module, audio_devices_t* pDevices, + uint32_t* pSamplingRate, audio_format_t* pFormat, + audio_channel_mask_t* pChannelMask) = 0; + // closes an audio input + virtual status_t closeInput(audio_io_handle_t input) = 0; + // + // misc control functions + // + + // set a stream volume for a particular output. For the same user setting, a given stream type + // can have different volumes for each output (destination device) it is attached to. + virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, + audio_io_handle_t output, int delayMs = 0) = 0; + + // invalidate a stream type, causing a reroute to an unspecified new output + virtual status_t invalidateStream(AudioSystem::stream_type stream) = 0; + + // function enabling to send proprietary informations directly from audio policy manager to + // audio hardware interface. + virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, + int delayMs = 0) = 0; + // function enabling to receive proprietary informations directly from audio hardware interface + // to audio policy manager. + virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) = 0; + + // request the playback of a tone on the specified stream: used for instance to replace + // notification sounds when playing over a telephony device during a phone call. + virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream) = 0; + virtual status_t stopTone() = 0; + + // set down link audio volume. + virtual status_t setVoiceVolume(float volume, int delayMs = 0) = 0; + + // move effect to the specified output + virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput, + audio_io_handle_t dstOutput) = 0; +}; + +extern "C" AudioPolicyInterface* createAudioPolicyManager( + AudioPolicyClientInterface* clientInterface); +extern "C" void destroyAudioPolicyManager(AudioPolicyInterface* interface); + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIOPOLICYINTERFACE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h new file mode 100644 index 0000000..ccc0d32 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h @@ -0,0 +1,567 @@ +/* + * Copyright (C) 2009 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 <cutils/config_utils.h> +#include <cutils/misc.h> +#include <hardware_legacy/AudioPolicyInterface.h> +#include <stdint.h> +#include <sys/types.h> +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/SortedVector.h> +#include <utils/Timers.h> + +namespace android_audio_legacy { +using android::DefaultKeyedVector; +using android::KeyedVector; +using android::SortedVector; + +// ---------------------------------------------------------------------------- + +#define MAX_DEVICE_ADDRESS_LEN 20 +// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB +#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5 +// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB +#define SONIFICATION_HEADSET_VOLUME_MIN 0.016 +// Time in milliseconds during which we consider that music is still active after a music +// track was stopped - see computeVolume() +#define SONIFICATION_HEADSET_MUSIC_DELAY 5000 +// Time in milliseconds after media stopped playing during which we consider that the +// sonification should be as unobtrusive as during the time media was playing. +#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000 +// Time in milliseconds during witch some streams are muted while the audio path +// is switched +#define MUTE_TIME_MS 2000 + +#define NUM_TEST_OUTPUTS 5 + +#define NUM_VOL_CURVE_KNEES 2 + +// Default minimum length allowed for offloading a compressed track +// Can be overridden by the audio.offload.min.duration.secs property +#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60 + +// ---------------------------------------------------------------------------- +// AudioPolicyManagerBase implements audio policy manager behavior common to all platforms. +// Each platform must implement an AudioPolicyManager class derived from AudioPolicyManagerBase +// and override methods for which the platform specific behavior differs from the implementation +// in AudioPolicyManagerBase. Even if no specific behavior is required, the AudioPolicyManager +// class must be implemented as well as the class factory function createAudioPolicyManager() +// and provided in a shared library libaudiopolicy.so. +// ---------------------------------------------------------------------------- + +class AudioPolicyManagerBase : public AudioPolicyInterface +#ifdef AUDIO_POLICY_TEST + , + public Thread +#endif // AUDIO_POLICY_TEST +{ + + public: + AudioPolicyManagerBase(AudioPolicyClientInterface* clientInterface); + virtual ~AudioPolicyManagerBase(); + + // AudioPolicyInterface + virtual status_t setDeviceConnectionState(audio_devices_t device, + AudioSystem::device_connection_state state, + const char* device_address); + virtual AudioSystem::device_connection_state getDeviceConnectionState( + audio_devices_t device, const char* device_address); + virtual void setPhoneState(int state); + virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config); + virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage); + virtual void setSystemProperty(const char* property, const char* value); + virtual status_t initCheck(); + virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::output_flags flags, + const audio_offload_info_t* offloadInfo); + virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE); + virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE); + virtual void releaseOutput(audio_io_handle_t output); + virtual audio_io_handle_t getInput(int inputSource, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::audio_in_acoustics acoustics); + + // indicates to the audio policy manager that the input starts being used. + virtual status_t startInput(audio_io_handle_t input); + + // indicates to the audio policy manager that the input stops being used. + virtual status_t stopInput(audio_io_handle_t input); + virtual void releaseInput(audio_io_handle_t input); + virtual void closeAllInputs(); + virtual void initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax); + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index, + audio_devices_t device); + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int* index, + audio_devices_t device); + + // return the strategy corresponding to a given stream type + virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream); + + // return the enabled output devices for the given stream type + virtual audio_devices_t getDevicesForStream(AudioSystem::stream_type stream); + + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t* desc = NULL); + virtual status_t registerEffect(const effect_descriptor_t* desc, audio_io_handle_t io, + uint32_t strategy, audio_session_t session, int id); + virtual status_t unregisterEffect(int id); + virtual status_t setEffectEnabled(int id, bool enabled); + + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const; + // return whether a stream is playing remotely, override to change the definition of + // local/remote playback, used for instance by notification manager to not make + // media players lose audio focus when not playing locally + virtual bool isStreamActiveRemotely(int stream, uint32_t inPastMs = 0) const; + virtual bool isSourceActive(audio_source_t source) const; + + virtual status_t dump(int fd); + + virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo); + + protected: + enum routing_strategy { + STRATEGY_MEDIA, + STRATEGY_PHONE, + STRATEGY_SONIFICATION, + STRATEGY_SONIFICATION_RESPECTFUL, + STRATEGY_DTMF, + STRATEGY_ENFORCED_AUDIBLE, + NUM_STRATEGIES + }; + + // 4 points to define the volume attenuation curve, each characterized by the volume + // index (from 0 to 100) at which they apply, and the attenuation in dB at that index. + // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl() + + enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4 }; + + class VolumeCurvePoint { + public: + int mIndex; + float mDBAttenuation; + }; + + // device categories used for volume curve management. + enum device_category { + DEVICE_CATEGORY_HEADSET, + DEVICE_CATEGORY_SPEAKER, + DEVICE_CATEGORY_EARPIECE, + DEVICE_CATEGORY_CNT + }; + + class IOProfile; + + class HwModule { + public: + HwModule(const char* name); + ~HwModule(); + + void dump(int fd); + + const char* const mName; // base name of the audio HW module (primary, a2dp ...) + audio_module_handle_t mHandle; + Vector<IOProfile*> mOutputProfiles; // output profiles exposed by this module + Vector<IOProfile*> mInputProfiles; // input profiles exposed by this module + }; + + // the IOProfile class describes the capabilities of an output or input stream. + // It is currently assumed that all combination of listed parameters are supported. + // It is used by the policy manager to determine if an output or input is suitable for + // a given use case, open/close it accordingly and connect/disconnect audio tracks + // to/from it. + class IOProfile { + public: + IOProfile(HwModule* module); + ~IOProfile(); + + bool isCompatibleProfile(audio_devices_t device, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + audio_output_flags_t flags) const; + + void dump(int fd); + void log(); + + // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats + // indicates the supported parameters should be read from the output stream + // after it is opened for the first time + Vector<uint32_t> mSamplingRates; // supported sampling rates + Vector<audio_channel_mask_t> mChannelMasks; // supported channel masks + Vector<audio_format_t> mFormats; // supported audio formats + audio_devices_t mSupportedDevices; // supported devices (devices this output can be + // routed to) + audio_output_flags_t mFlags; // attribute flags (e.g primary output, + // direct output...). For outputs only. + HwModule* mModule; // audio HW module exposing this I/O stream + }; + + // default volume curve + static const VolumeCurvePoint sDefaultVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // default volume curve for media strategy + static const VolumeCurvePoint sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // volume curve for media strategy on speakers + static const VolumeCurvePoint sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // volume curve for sonification strategy on speakers + static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint + sSpeakerSonificationVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sHeadsetSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // default volume curves per stream and device category. See initializeVolumeCurves() + static const VolumeCurvePoint* sVolumeProfiles[AudioSystem::NUM_STREAM_TYPES] + [DEVICE_CATEGORY_CNT]; + + // descriptor for audio outputs. Used to maintain current configuration of each opened audio + // output and keep track of the usage of this output by each audio stream type. + class AudioOutputDescriptor { + public: + AudioOutputDescriptor(const IOProfile* profile); + + status_t dump(int fd); + + audio_devices_t device() const; + void changeRefCount(AudioSystem::stream_type stream, int delta); + + bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); } + audio_devices_t supportedDevices(); + uint32_t latency(); + bool sharesHwModuleWith(const AudioOutputDescriptor* outputDesc); + bool isActive(uint32_t inPastMs = 0) const; + bool isStreamActive(AudioSystem::stream_type stream, uint32_t inPastMs = 0, + nsecs_t sysTime = 0) const; + bool isStrategyActive(routing_strategy strategy, uint32_t inPastMs = 0, + nsecs_t sysTime = 0) const; + + audio_io_handle_t mId; // output handle + uint32_t mSamplingRate; // + audio_format_t mFormat; // + audio_channel_mask_t mChannelMask; // output configuration + uint32_t mLatency; // + audio_output_flags_t mFlags; // + audio_devices_t mDevice; // current device this output is routed to + uint32_t mRefCount[AudioSystem::NUM_STREAM_TYPES]; // number of streams of each type using + // this output + nsecs_t mStopTime[AudioSystem::NUM_STREAM_TYPES]; + AudioOutputDescriptor* mOutput1; // used by duplicated outputs: first output + AudioOutputDescriptor* mOutput2; // used by duplicated outputs: second output + float mCurVolume[AudioSystem::NUM_STREAM_TYPES]; // current stream volume + int mMuteCount[AudioSystem::NUM_STREAM_TYPES]; // mute request counter + const IOProfile* mProfile; // I/O profile this output derives from + bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible + // device selection. See + // checkDeviceMuteStrategies() + uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) + bool mForceRouting; // Next routing for this output will be forced as current device routed + // is null + }; + + // descriptor for audio inputs. Used to maintain current configuration of each opened audio + // input and keep track of the usage of this input. + class AudioInputDescriptor { + public: + AudioInputDescriptor(const IOProfile* profile); + + status_t dump(int fd); + + audio_io_handle_t mId; // input handle + uint32_t mSamplingRate; // + audio_format_t mFormat; // input configuration + audio_channel_mask_t mChannelMask; // + audio_devices_t mDevice; // current device this input is routed to + uint32_t mRefCount; // number of AudioRecord clients using this output + int mInputSource; // input source selected by application (mediarecorder.h) + const IOProfile* mProfile; // I/O profile this output derives from + }; + + // stream descriptor used for volume control + class StreamDescriptor { + public: + StreamDescriptor(); + + int getVolumeIndex(audio_devices_t device); + void dump(int fd); + + int mIndexMin; // min volume index + int mIndexMax; // max volume index + KeyedVector<audio_devices_t, int> mIndexCur; // current volume index per device + bool mCanBeMuted; // true is the stream can be muted + + const VolumeCurvePoint* mVolumeCurve[DEVICE_CATEGORY_CNT]; + }; + + // stream descriptor used for volume control + class EffectDescriptor { + public: + status_t dump(int fd); + + int mIo; // io the effect is attached to + routing_strategy mStrategy; // routing strategy the effect is associated to + audio_session_t mSession; // audio session the effect is on + effect_descriptor_t mDesc; // effect descriptor + bool mEnabled; // enabled state: CPU load being used or not + }; + + void addOutput(audio_io_handle_t id, AudioOutputDescriptor* outputDesc); + void addInput(audio_io_handle_t id, AudioInputDescriptor* inputDesc); + + // return the strategy corresponding to a given stream type + static routing_strategy getStrategy(AudioSystem::stream_type stream); + + // return appropriate device for streams handled by the specified strategy according to current + // phone state, connected devices... + // if fromCache is true, the device is returned from mDeviceForStrategy[], + // otherwise it is determine by current state + // (device connected,phone state, force use, a2dp output...) + // This allows to: + // 1 speed up process when the state is stable (when starting or stopping an output) + // 2 access to either current device selection (fromCache == true) or + // "future" device selection (fromCache == false) when called from a context + // where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND + // before updateDevicesAndOutputs() is called. + virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache); + + // change the route of the specified output. Returns the number of ms we have slept to + // allow new routing to take effect in certain cases. + uint32_t setOutputDevice(audio_io_handle_t output, audio_devices_t device, bool force = false, + int delayMs = 0); + + // select input device corresponding to requested audio source + virtual audio_devices_t getDeviceForInputSource(int inputSource); + + // return io handle of active input or 0 if no input is active + // Only considers inputs from physical devices (e.g. main mic, headset mic) when + // ignoreVirtualInputs is true. + audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true); + + // initialize volume curves for each strategy and device category + void initializeVolumeCurves(); + + // compute the actual volume for a given stream according to the requested index and a + // particular device + virtual float computeVolume(int stream, int index, audio_io_handle_t output, + audio_devices_t device); + + // check that volume change is permitted, compute and send new volume to audio hardware + status_t checkAndSetVolume(int stream, int index, audio_io_handle_t output, + audio_devices_t device, int delayMs = 0, bool force = false); + + // apply all stream volumes to the specified output and device + void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, + bool force = false); + + // Mute or unmute all streams handled by the specified strategy on the specified output + void setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, + int delayMs = 0, audio_devices_t device = (audio_devices_t)0); + + // Mute or unmute the stream on the specified output + void setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs = 0, + audio_devices_t device = (audio_devices_t)0); + + // handle special cases for sonification strategy while in call: mute streams or replace by + // a special tone in the device used for communication + void handleIncallSonification(int stream, bool starting, bool stateChange); + + // true if device is in a telephony or VoIP call + virtual bool isInCall(); + + // true if given state represents a device in a telephony or VoIP call + virtual bool isStateInCall(int state); + + // when a device is connected, checks if an open output can be routed + // to this device. If none is open, tries to open one of the available outputs. + // Returns an output suitable to this device or 0. + // when a device is disconnected, checks if an output is not used any more and + // returns its handle if any. + // transfers the audio tracks and effects from one output thread to another accordingly. + status_t checkOutputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector<audio_io_handle_t>& outputs, + const String8 paramStr); + + status_t checkInputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector<audio_io_handle_t>& inputs, const String8 paramStr); + + // close an output and its companion duplicating output. + void closeOutput(audio_io_handle_t output); + + // checks and if necessary changes outputs used for all strategies. + // must be called every time a condition that affects the output choice for a given strategy + // changes: connected device, phone state, force use... + // Must be called before updateDevicesAndOutputs() + void checkOutputForStrategy(routing_strategy strategy); + + // Same as checkOutputForStrategy() but for a all strategies in order of priority + void checkOutputForAllStrategies(); + + // manages A2DP output suspend/restore according to phone state and BT SCO usage + void checkA2dpSuspend(); + + // returns the A2DP output handle if it is open or 0 otherwise + audio_io_handle_t getA2dpOutput(); + + // selects the most appropriate device on output for current state + // must be called every time a condition that affects the device choice for a given output is + // changed: connected device, phone state, force use, output start, output stop.. + // see getDeviceForStrategy() for the use of fromCache parameter + + audio_devices_t getNewDevice(audio_io_handle_t output, bool fromCache); + // updates cache of device used by all strategies (mDeviceForStrategy[]) + // must be called every time a condition that affects the device choice for a given strategy is + // changed: connected device, phone state, force use... + // cached values are used by getDeviceForStrategy() if parameter fromCache is true. + // Must be called after checkOutputForAllStrategies() + + void updateDevicesAndOutputs(); + + virtual uint32_t getMaxEffectsCpuLoad(); + virtual uint32_t getMaxEffectsMemory(); +#ifdef AUDIO_POLICY_TEST + virtual bool threadLoop(); + void exit(); + int testOutputIndex(audio_io_handle_t output); +#endif // AUDIO_POLICY_TEST + + status_t setEffectEnabled(EffectDescriptor* pDesc, bool enabled); + + // returns the category the device belongs to with regard to volume curve management + static device_category getDeviceCategory(audio_devices_t device); + + // extract one device relevant for volume control from multiple device selection + static audio_devices_t getDeviceForVolume(audio_devices_t device); + + SortedVector<audio_io_handle_t> getOutputsForDevice( + audio_devices_t device, + DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor*> openOutputs); + bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1, + SortedVector<audio_io_handle_t>& outputs2); + + // mute/unmute strategies using an incompatible device combination + // if muting, wait for the audio in pcm buffer to be drained before proceeding + // if unmuting, unmute only after the specified delay + // Returns the number of ms waited + uint32_t checkDeviceMuteStrategies(AudioOutputDescriptor* outputDesc, + audio_devices_t prevDevice, uint32_t delayMs); + + audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs, + AudioSystem::output_flags flags); + IOProfile* getInputProfile(audio_devices_t device, uint32_t samplingRate, audio_format_t format, + audio_channel_mask_t channelMask); + IOProfile* getProfileForDirectOutput(audio_devices_t device, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + audio_output_flags_t flags); + + audio_io_handle_t selectOutputForEffects(const SortedVector<audio_io_handle_t>& outputs); + + bool isNonOffloadableEffectEnabled(); + + // + // Audio policy configuration file parsing (audio_policy.conf) + // + static uint32_t stringToEnum(const struct StringToEnum* table, size_t size, const char* name); + static bool stringToBool(const char* value); + static audio_output_flags_t parseFlagNames(char* name); + static audio_devices_t parseDeviceNames(char* name); + void loadSamplingRates(char* name, IOProfile* profile); + void loadFormats(char* name, IOProfile* profile); + void loadOutChannels(char* name, IOProfile* profile); + void loadInChannels(char* name, IOProfile* profile); + status_t loadOutput(cnode* root, HwModule* module); + status_t loadInput(cnode* root, HwModule* module); + void loadHwModule(cnode* root); + void loadHwModules(cnode* root); + void loadGlobalConfig(cnode* root); + status_t loadAudioPolicyConfig(const char* path); + void defaultAudioPolicyConfig(void); + + AudioPolicyClientInterface* mpClientInterface; // audio policy client interface + audio_io_handle_t mPrimaryOutput; // primary output handle + // list of descriptors for outputs currently opened + DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor*> mOutputs; + // copy of mOutputs before setDeviceConnectionState() opens new outputs + // reset to mOutputs when updateDevicesAndOutputs() is called. + DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor*> mPreviousOutputs; + + // list of input descriptors currently opened + DefaultKeyedVector<audio_io_handle_t, AudioInputDescriptor*> mInputs; + + audio_devices_t mAvailableOutputDevices; // bit field of all available output devices + audio_devices_t mAvailableInputDevices; // bit field of all available input devices + // without AUDIO_DEVICE_BIT_IN to allow direct bit + // field comparisons + int mPhoneState; // current phone state + AudioSystem::forced_config + mForceUse[AudioSystem::NUM_FORCE_USE]; // current forced use configuration + + StreamDescriptor + mStreams[AudioSystem::NUM_STREAM_TYPES]; // stream descriptors for volume control + String8 mA2dpDeviceAddress; // A2DP device MAC address + String8 mScoDeviceAddress; // SCO device MAC address + String8 mUsbOutCardAndDevice; // USB audio ALSA card and device numbers: + // card=<card_number>;device=<><device_number> + bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected + audio_devices_t mDeviceForStrategy[NUM_STRATEGIES]; + float mLastVoiceVolume; // last voice volume value sent to audio HAL + + // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units + static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000; + // Maximum memory allocated to audio effects in KB + static const uint32_t MAX_EFFECTS_MEMORY = 512; + uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects + uint32_t mTotalEffectsMemory; // current memory used by effects + KeyedVector<int, EffectDescriptor*> mEffects; // list of registered audio effects + bool mA2dpSuspended; // true if A2DP output is suspended + bool mHasA2dp; // true on platforms with support for bluetooth A2DP + bool mHasUsb; // true on platforms with support for USB audio + bool mHasRemoteSubmix; // true on platforms with support for remote presentation of a submix + audio_devices_t mAttachedOutputDevices; // output devices always available on the platform + audio_devices_t mDefaultOutputDevice; // output device selected by default at boot time + // (must be in mAttachedOutputDevices) + bool mSpeakerDrcEnabled; // true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path + // to boost soft sounds, used to adjust volume curves accordingly + + Vector<HwModule*> mHwModules; + +#ifdef AUDIO_POLICY_TEST + Mutex mLock; + Condition mWaitWorkCV; + + int mCurOutput; + bool mDirectOutput; + audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS]; + int mTestInput; + uint32_t mTestDevice; + uint32_t mTestSamplingRate; + uint32_t mTestFormat; + uint32_t mTestChannels; + uint32_t mTestLatencyMs; +#endif // AUDIO_POLICY_TEST + + private: + static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, + int indexInUi); + // updates device caching and output for streams that can influence the + // routing of notifications + void handleNotificationRoutingForStream(AudioSystem::stream_type stream); + static bool isVirtualInputDevice(audio_devices_t device); +}; + +}; // namespace android_audio_legacy diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h new file mode 100644 index 0000000..943b0db --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2008 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 ANDROID_AUDIOSYSTEM_LEGACY_H_ +#define ANDROID_AUDIOSYSTEM_LEGACY_H_ + +#include <cutils/bitops.h> +#include <media/AudioParameter.h> +#include <utils/Errors.h> + +#include <system/audio.h> +#include <system/audio_policy.h> + +namespace android_audio_legacy { + +using android::AudioParameter; +using android::status_t; + +enum { + OK = android::OK, + NO_ERROR = android::NO_ERROR, + + UNKNOWN_ERROR = android::UNKNOWN_ERROR, + + NO_MEMORY = android::NO_MEMORY, + INVALID_OPERATION = android::INVALID_OPERATION, + BAD_VALUE = android::BAD_VALUE, + BAD_TYPE = android::BAD_TYPE, + NAME_NOT_FOUND = android::NAME_NOT_FOUND, + PERMISSION_DENIED = android::PERMISSION_DENIED, + NO_INIT = android::NO_INIT, + ALREADY_EXISTS = android::ALREADY_EXISTS, + DEAD_OBJECT = android::DEAD_OBJECT, + FAILED_TRANSACTION = android::FAILED_TRANSACTION, + BAD_INDEX = android::BAD_INDEX, + NOT_ENOUGH_DATA = android::NOT_ENOUGH_DATA, + WOULD_BLOCK = android::WOULD_BLOCK, + TIMED_OUT = android::TIMED_OUT, + UNKNOWN_TRANSACTION = android::UNKNOWN_TRANSACTION, +}; + +enum audio_source { + AUDIO_SOURCE_DEFAULT = 0, + AUDIO_SOURCE_MIC = 1, + AUDIO_SOURCE_VOICE_UPLINK = 2, + AUDIO_SOURCE_VOICE_DOWNLINK = 3, + AUDIO_SOURCE_VOICE_CALL = 4, + AUDIO_SOURCE_CAMCORDER = 5, + AUDIO_SOURCE_VOICE_RECOGNITION = 6, + AUDIO_SOURCE_VOICE_COMMUNICATION = 7, + AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_COMMUNICATION, + + AUDIO_SOURCE_LIST_END // must be last - used to validate audio source type +}; + +class AudioSystem { + public: +#if 1 + enum stream_type { + DEFAULT = -1, + VOICE_CALL = 0, + SYSTEM = 1, + RING = 2, + MUSIC = 3, + ALARM = 4, + NOTIFICATION = 5, + BLUETOOTH_SCO = 6, + ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker + DTMF = 8, + TTS = 9, + NUM_STREAM_TYPES + }; + + // Audio sub formats (see AudioSystem::audio_format). + enum pcm_sub_format { + PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility + PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility + }; + + enum audio_sessions { + SESSION_OUTPUT_STAGE = AUDIO_SESSION_OUTPUT_STAGE, + SESSION_OUTPUT_MIX = AUDIO_SESSION_OUTPUT_MIX, + }; + + // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to + // specify bit rate, stereo mode, version... + enum mp3_sub_format { + // TODO + }; + + // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient + // or octet aligned, encoding mode for recording... + enum amr_sub_format { + // TODO + }; + + // AAC sub format field definition: specify profile or bitrate for recording... + enum aac_sub_format { + // TODO + }; + + // VORBIS sub format field definition: specify quality for recording... + enum vorbis_sub_format { + // TODO + }; + + // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 + // bits). The main format indicates the main codec type. The sub format field indicates options + // and parameters for each format. The sub format is mainly used for record to indicate for + // instance the requested bitrate or profile. It can also be used for certain formats to give + // informations not present in the encoded audio stream (e.g. octet alignement for AMR). + enum audio_format { + INVALID_FORMAT = -1, + FORMAT_DEFAULT = 0, + PCM = 0x00000000, // must be 0 for backward compatibility + MP3 = 0x01000000, + AMR_NB = 0x02000000, + AMR_WB = 0x03000000, + AAC = 0x04000000, + HE_AAC_V1 = 0x05000000, + HE_AAC_V2 = 0x06000000, + VORBIS = 0x07000000, + MAIN_FORMAT_MASK = 0xFF000000, + SUB_FORMAT_MASK = 0x00FFFFFF, + // Aliases + PCM_16_BIT = (PCM | PCM_SUB_16_BIT), + PCM_8_BIT = (PCM | PCM_SUB_8_BIT) + }; + + enum audio_channels { + // output channels + CHANNEL_OUT_FRONT_LEFT = 0x1, + CHANNEL_OUT_FRONT_RIGHT = 0x2, + CHANNEL_OUT_FRONT_CENTER = 0x4, + CHANNEL_OUT_LOW_FREQUENCY = 0x8, + CHANNEL_OUT_BACK_LEFT = 0x10, + CHANNEL_OUT_BACK_RIGHT = 0x20, + CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40, + CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80, + CHANNEL_OUT_BACK_CENTER = 0x100, + CHANNEL_OUT_SIDE_LEFT = 0x200, + CHANNEL_OUT_SIDE_RIGHT = 0x400, + CHANNEL_OUT_TOP_CENTER = 0x800, + CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000, + CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000, + CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000, + CHANNEL_OUT_TOP_BACK_LEFT = 0x8000, + CHANNEL_OUT_TOP_BACK_CENTER = 0x10000, + CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000, + + CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT, + CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT), + CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), + CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER), + CHANNEL_OUT_5POINT1 = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), + // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1 + CHANNEL_OUT_7POINT1 = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT), + CHANNEL_OUT_ALL = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | + CHANNEL_OUT_BACK_CENTER | CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT | + CHANNEL_OUT_TOP_CENTER | CHANNEL_OUT_TOP_FRONT_LEFT | + CHANNEL_OUT_TOP_FRONT_CENTER | CHANNEL_OUT_TOP_FRONT_RIGHT | + CHANNEL_OUT_TOP_BACK_LEFT | CHANNEL_OUT_TOP_BACK_CENTER | + CHANNEL_OUT_TOP_BACK_RIGHT), + + // input channels + CHANNEL_IN_LEFT = 0x4, + CHANNEL_IN_RIGHT = 0x8, + CHANNEL_IN_FRONT = 0x10, + CHANNEL_IN_BACK = 0x20, + CHANNEL_IN_LEFT_PROCESSED = 0x40, + CHANNEL_IN_RIGHT_PROCESSED = 0x80, + CHANNEL_IN_FRONT_PROCESSED = 0x100, + CHANNEL_IN_BACK_PROCESSED = 0x200, + CHANNEL_IN_PRESSURE = 0x400, + CHANNEL_IN_X_AXIS = 0x800, + CHANNEL_IN_Y_AXIS = 0x1000, + CHANNEL_IN_Z_AXIS = 0x2000, + CHANNEL_IN_VOICE_UPLINK = 0x4000, + CHANNEL_IN_VOICE_DNLINK = 0x8000, + CHANNEL_IN_MONO = CHANNEL_IN_FRONT, + CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT), + CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK | + CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | + CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED | + CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | + CHANNEL_IN_Z_AXIS | CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK) + }; + + enum audio_mode { + MODE_INVALID = -2, + MODE_CURRENT = -1, + MODE_NORMAL = 0, + MODE_RINGTONE, + MODE_IN_CALL, + MODE_IN_COMMUNICATION, + NUM_MODES // not a valid entry, denotes end-of-list + }; + + enum audio_in_acoustics { + AGC_ENABLE = 0x0001, + AGC_DISABLE = 0, + NS_ENABLE = 0x0002, + NS_DISABLE = 0, + TX_IIR_ENABLE = 0x0004, + TX_DISABLE = 0 + }; + + // DO NOT USE: the "audio_devices" enumeration below is obsolete, use type "audio_devices_t" and + // audio device enumeration from system/audio.h instead. + enum audio_devices { + // output devices + DEVICE_OUT_EARPIECE = 0x1, + DEVICE_OUT_SPEAKER = 0x2, + DEVICE_OUT_WIRED_HEADSET = 0x4, + DEVICE_OUT_WIRED_HEADPHONE = 0x8, + DEVICE_OUT_BLUETOOTH_SCO = 0x10, + DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, + DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, + DEVICE_OUT_BLUETOOTH_A2DP = 0x80, + DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, + DEVICE_OUT_AUX_DIGITAL = 0x400, + DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800, + DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000, + DEVICE_OUT_DEFAULT = 0x8000, + DEVICE_OUT_ALL = + (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | + DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | + DEVICE_OUT_BLUETOOTH_SCO_HEADSET | DEVICE_OUT_BLUETOOTH_SCO_CARKIT | + DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | + DEVICE_OUT_ANLG_DOCK_HEADSET | DEVICE_OUT_DGTL_DOCK_HEADSET | DEVICE_OUT_DEFAULT), + DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), + + // input devices + DEVICE_IN_COMMUNICATION = 0x10000, + DEVICE_IN_AMBIENT = 0x20000, + DEVICE_IN_BUILTIN_MIC = 0x40000, + DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000, + DEVICE_IN_WIRED_HEADSET = 0x100000, + DEVICE_IN_AUX_DIGITAL = 0x200000, + DEVICE_IN_VOICE_CALL = 0x400000, + DEVICE_IN_BACK_MIC = 0x800000, + DEVICE_IN_DEFAULT = 0x80000000, + + DEVICE_IN_ALL = + (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC | + DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL | + DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT) + }; + + // request to open a direct output with getOutput() (by opposition to sharing an output with + // other AudioTracks) + enum output_flags { OUTPUT_FLAG_INDIRECT = 0x0, OUTPUT_FLAG_DIRECT = 0x1 }; + + // device categories used for setForceUse() + enum forced_config { + FORCE_NONE, + FORCE_SPEAKER, + FORCE_HEADPHONES, + FORCE_BT_SCO, + FORCE_BT_A2DP, + FORCE_WIRED_ACCESSORY, + FORCE_BT_CAR_DOCK, + FORCE_BT_DESK_DOCK, + FORCE_ANALOG_DOCK, + FORCE_DIGITAL_DOCK, + FORCE_NO_BT_A2DP, + FORCE_SYSTEM_ENFORCED, + NUM_FORCE_CONFIG, + FORCE_DEFAULT = FORCE_NONE + }; + + // usages used for setForceUse() + enum force_use { + FOR_COMMUNICATION, + FOR_MEDIA, + FOR_RECORD, + FOR_DOCK, + FOR_SYSTEM, + NUM_FORCE_USE + }; + + // + // AudioPolicyService interface + // + + // device connection states used for setDeviceConnectionState() + enum device_connection_state { + DEVICE_STATE_UNAVAILABLE, + DEVICE_STATE_AVAILABLE, + NUM_DEVICE_STATES + }; + +#endif + + static uint32_t popCount(uint32_t u) { return popcount(u); } + +#if 1 + static bool isOutputDevice(audio_devices device) { + if ((popcount(device) == 1) && ((device & ~DEVICE_OUT_ALL) == 0)) + return true; + else + return false; + } + static bool isInputDevice(audio_devices device) { + if ((popcount(device) == 1) && ((device & ~DEVICE_IN_ALL) == 0)) + return true; + else + return false; + } + static bool isA2dpDevice(audio_devices device) { + return audio_is_a2dp_device((audio_devices_t)device); + } + static bool isBluetoothScoDevice(audio_devices device) { + return audio_is_bluetooth_sco_device((audio_devices_t)device); + } + static bool isValidFormat(uint32_t format) { + return audio_is_valid_format((audio_format_t)format); + } + static bool isLinearPCM(uint32_t format) { return audio_is_linear_pcm((audio_format_t)format); } + static bool isOutputChannel(audio_channel_mask_t channel) { + return audio_is_output_channel(channel); + } + static bool isInputChannel(audio_channel_mask_t channel) { + return audio_is_input_channel(channel); + } + +#endif +}; + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIOSYSTEM_LEGACY_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h new file mode 100644 index 0000000..158ff59 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007 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 ANDROID_HARDWARE_IMOUNTSERVICE_H +#define ANDROID_HARDWARE_IMOUNTSERVICE_H + +#include <binder/IInterface.h> +#include <utils/String16.h> + +namespace android { + +// ---------------------------------------------------------------------- + +class IMountService : public IInterface { + public: + static const int OperationSucceeded = 0; + static const int OperationFailedInternalError = -1; + static const int OperationFailedNoMedia = -2; + static const int OperationFailedMediaBlank = -3; + static const int OperationFailedMediaCorrupt = -4; + static const int OperationFailedVolumeNotMounted = -5; + + public: + DECLARE_META_INTERFACE(MountService); + + virtual void getShareMethodList() = 0; + virtual bool getShareMethodAvailable(String16 method) = 0; + virtual int shareVolume(String16 path, String16 method) = 0; + virtual int unshareVolume(String16 path, String16 method) = 0; + virtual bool getVolumeShared(String16 path, String16 method) = 0; + virtual int mountVolume(String16 path) = 0; + virtual int unmountVolume(String16 path) = 0; + virtual int formatVolume(String16 path) = 0; + virtual String16 getVolumeState(String16 mountPoint) = 0; + virtual int createSecureContainer(String16 id, int sizeMb, String16 fstype, String16 key, + int ownerUid) = 0; + virtual int finalizeSecureContainer(String16 id) = 0; + virtual int destroySecureContainer(String16 id) = 0; + virtual int mountSecureContainer(String16 id, String16 key, int ownerUid) = 0; + virtual int unmountSecureContainer(String16 id) = 0; + virtual int renameSecureContainer(String16 oldId, String16 newId) = 0; + virtual String16 getSecureContainerPath(String16 id) = 0; + virtual void getSecureContainerList() = 0; + virtual void shutdown() = 0; +}; + +// ---------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_HARDWARE_IMOUNTSERVICE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h new file mode 100644 index 0000000..13d62f9 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 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 ANDROID_AUDIO_POLICY_CONF_H +#define ANDROID_AUDIO_POLICY_CONF_H + +///////////////////////////////////////////////// +// Definitions for audio policy configuration file (audio_policy.conf) +///////////////////////////////////////////////// + +#define AUDIO_HARDWARE_MODULE_ID_MAX_LEN 32 + +#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf" +#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf" + +// global configuration +#define GLOBAL_CONFIG_TAG "global_configuration" + +#define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices" +#define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device" +#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices" +#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled" + +// hw modules descriptions +#define AUDIO_HW_MODULE_TAG "audio_hw_modules" + +#define OUTPUTS_TAG "outputs" +#define INPUTS_TAG "inputs" + +#define SAMPLING_RATES_TAG "sampling_rates" +#define FORMATS_TAG "formats" +#define CHANNELS_TAG "channel_masks" +#define DEVICES_TAG "devices" +#define FLAGS_TAG "flags" + +#define DYNAMIC_VALUE_TAG \ + "dynamic" // special value for "channel_masks", "sampling_rates" and + // "formats" in outputs descriptors indicating that supported + // values should be queried after opening the output. + +#endif // ANDROID_AUDIO_POLICY_CONF_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h new file mode 100644 index 0000000..c6c52c6 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h @@ -0,0 +1,427 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_GSCAN_H__ +#define __WIFI_HAL_GSCAN_H__ + +// Define static_assert() unless already defined by compiler. +#ifndef __has_feature +#define __has_feature(__x) 0 +#endif +#if !(__has_feature(cxx_static_assert)) && !defined(static_assert) +#define static_assert(__b, __m) \ + extern int compile_time_assert_failed[(__b) ? 1 : -1] __attribute__((unused)); +#endif + +/* AP Scans */ + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, // 2.4 GHz + WIFI_BAND_A = 2, // 5 GHz without DFS + WIFI_BAND_A_DFS = 4, // 5 GHz DFS only + WIFI_BAND_A_WITH_DFS = 6, // 5 GHz with DFS + WIFI_BAND_ABG = 3, // 2.4 GHz + 5 GHz; no DFS + WIFI_BAND_ABG_WITH_DFS = 7, // 2.4 GHz + 5 GHz with DFS +} wifi_band; + +#define MAX_CHANNELS 16 +#define MAX_BUCKETS 16 +#define MAX_HOTLIST_APS 128 +#define MAX_SIGNIFICANT_CHANGE_APS 64 +#define MAX_EPNO_NETWORKS 64 +#define MAX_HOTLIST_SSID 8 +#define MAX_AP_CACHE_PER_SCAN 32 + +wifi_error wifi_get_valid_channels(wifi_interface_handle handle, int band, int max_channels, + wifi_channel* channels, int* num_channels); + +typedef struct { + int max_scan_cache_size; // total space allocated for scan (in bytes) + int max_scan_buckets; // maximum number of channel buckets + int max_ap_cache_per_scan; // maximum number of APs that can be stored per scan + int max_rssi_sample_size; // number of RSSI samples used for averaging RSSI + int max_scan_reporting_threshold; // max possible report_threshold as described + // in wifi_scan_cmd_params + int max_hotlist_bssids; // maximum number of entries for hotlist BSSIDs + int max_hotlist_ssids; // maximum number of entries for hotlist SSIDs + int max_significant_wifi_change_aps; // maximum number of entries for + // significant wifi change APs + int max_bssid_history_entries; // number of BSSID/RSSI entries that device can hold + int max_number_epno_networks; // max number of epno entries + int max_number_epno_networks_by_ssid; // max number of epno entries if ssid is specified, + // that is, epno entries for which an exact match is + // required, or entries corresponding to hidden ssids + int max_number_of_white_listed_ssid; // max number of white listed SSIDs, M target is 2 to 4 +} wifi_gscan_capabilities; + +wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, + wifi_gscan_capabilities* capabilities); + +typedef enum { + WIFI_SCAN_RESULTS_AVAILABLE, // reported when REPORT_EVENTS_EACH_SCAN is set and a scan + // completes. WIFI_SCAN_THRESHOLD_NUM_SCANS or + // WIFI_SCAN_THRESHOLD_PERCENT can be reported instead if the + // reason for the event is available; however, at most one of + // these events should be reported per scan. If there are + // multiple buckets that were scanned this period and one has the + // EACH_SCAN flag set then this event should be prefered. + WIFI_SCAN_THRESHOLD_NUM_SCANS, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and + // report_threshold_num_scans is reached. + WIFI_SCAN_THRESHOLD_PERCENT, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and + // report_threshold_percent is reached. + WIFI_SCAN_FAILED, // reported when currently executing gscans have failed. + // start_gscan will need to be called again in order to continue + // scanning. This is intended to indicate abnormal scan + // terminations (not those as a result of stop_gscan). +} wifi_scan_event; + +/* Format of information elements found in the beacon */ +typedef struct { + byte id; // element identifier + byte len; // number of bytes to follow + byte data[]; +} wifi_information_element; + +typedef struct { + wifi_timestamp ts; // time since boot (in microsecond) when the result was + // retrieved + char ssid[32 + 1]; // null terminated + mac_addr bssid; + wifi_channel channel; // channel frequency in MHz + wifi_rssi rssi; // in db + wifi_timespan rtt; // in nanoseconds + wifi_timespan rtt_sd; // standard deviation in rtt + unsigned short beacon_period; // period advertised in the beacon + unsigned short capability; // capabilities advertised in the beacon + unsigned int ie_length; // size of the ie_data blob + char ie_data[1]; // blob of all the information elements found in the + // beacon; this data should be a packed list of + // wifi_information_element objects, one after the other. + // other fields +} wifi_scan_result; + +static_assert( + MAX_BUCKETS <= 8 * sizeof(unsigned), + "The buckets_scanned bitset is represented by an unsigned int and cannot support this many " + "buckets on this platform."); +typedef struct { + /* reported when each probe response is received, if report_events + * enabled in wifi_scan_cmd_params. buckets_scanned is a bitset of the + * buckets that are currently being scanned. See the buckets_scanned field + * in the wifi_cached_scan_results struct for more details. + */ + void (*on_full_scan_result)(wifi_request_id id, wifi_scan_result* result, + unsigned buckets_scanned); + + /* indicates progress of scanning statemachine */ + void (*on_scan_event)(wifi_request_id id, wifi_scan_event event); + +} wifi_scan_result_handler; + +typedef struct { + wifi_channel channel; // frequency + int dwellTimeMs; // dwell time hint + int passive; // 0 => active, 1 => passive scan; ignored for DFS + /* Add channel class */ +} wifi_scan_channel_spec; + +#define REPORT_EVENTS_EACH_SCAN (1 << 0) +#define REPORT_EVENTS_FULL_RESULTS (1 << 1) +#define REPORT_EVENTS_NO_BATCH (1 << 2) + +typedef struct { + int bucket; // bucket index, 0 based + wifi_band band; // when UNSPECIFIED, use channel list + int period; // desired period, in millisecond; if this is too + // low, the firmware should choose to generate results as + // fast as it can instead of failing the command. + // for exponential backoff bucket this is the min_period + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the + * history buffer + */ + byte report_events; + int max_period; // if max_period is non zero or different than period, then this bucket is + // an exponential backoff bucket and the scan period will grow exponentially + // as per formula: actual_period(N) = period * (base ^ (N/step_count)) + // to a maximum period of max_period + int base; // for exponential back off bucket: multiplier: new_period=old_period*base + int step_count; // for exponential back off bucket, number of scans to perform for a given + // period + + int num_channels; + // channels to scan; these may include DFS channels + // Note that a given channel may appear in multiple buckets + wifi_scan_channel_spec channels[MAX_CHANNELS]; +} wifi_scan_bucket_spec; + +typedef struct { + int base_period; // base timer period in ms + int max_ap_per_scan; // number of access points to store in each scan entry in + // the BSSID/RSSI history buffer (keep the highest RSSI + // access points) + int report_threshold_percent; // in %, when scan buffer is this much full, wake up apps + // processor + int report_threshold_num_scans; // in number of scans, wake up AP after these many scans + int num_buckets; + wifi_scan_bucket_spec buckets[MAX_BUCKETS]; +} wifi_scan_cmd_params; + +/* + * Start periodic GSCAN + * When this is called all requested buckets should be scanned, starting the beginning of the cycle + * + * For example: + * If there are two buckets specified + * - Bucket 1: period=10s + * - Bucket 2: period=20s + * - Bucket 3: period=30s + * Then the following scans should occur + * - t=0 buckets 1, 2, and 3 are scanned + * - t=10 bucket 1 is scanned + * - t=20 bucket 1 and 2 are scanned + * - t=30 bucket 1 and 3 are scanned + * - t=40 bucket 1 and 2 are scanned + * - t=50 bucket 1 is scanned + * - t=60 buckets 1, 2, and 3 are scanned + * - and the patter repeats + * + * If any scan does not occur or is incomplete (error, interrupted, etc) then a cached scan result + * should still be recorded with the WIFI_SCAN_FLAG_INTERRUPTED flag set. + */ +wifi_error wifi_start_gscan(wifi_request_id id, wifi_interface_handle iface, + wifi_scan_cmd_params params, wifi_scan_result_handler handler); + +/* Stop periodic GSCAN */ +wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface); + +typedef enum { + WIFI_SCAN_FLAG_INTERRUPTED = 1 // Indicates that scan results are not complete because + // probes were not sent on some channels +} wifi_scan_flags; + +/* Get the GSCAN cached scan results */ +typedef struct { + int scan_id; // a unique identifier for the scan unit + int flags; // a bitmask with additional + // information about scan. + unsigned buckets_scanned; // a bitset of the buckets that were scanned. + // for example a value of 13 (0b1101) would + // indicate that buckets 0, 2 and 3 were + // scanned to produce this list of results. + // should be set to 0 if this information is + // not available. + int num_results; // number of bssids retrieved by the scan + wifi_scan_result results[MAX_AP_CACHE_PER_SCAN]; // scan results - one for each bssid +} wifi_cached_scan_results; + +wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, int max, + wifi_cached_scan_results* results, int* num); + +/* BSSID Hotlist */ +typedef struct { + void (*on_hotlist_ap_found)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); + void (*on_hotlist_ap_lost)(wifi_request_id id, unsigned num_results, wifi_scan_result* results); +} wifi_hotlist_ap_found_handler; + +typedef struct { + mac_addr bssid; // AP BSSID + wifi_rssi low; // low threshold + wifi_rssi high; // high threshold +} ap_threshold_param; + +typedef struct { + int lost_ap_sample_size; + int num_bssid; // number of hotlist APs + ap_threshold_param ap[MAX_HOTLIST_APS]; // hotlist APs +} wifi_bssid_hotlist_params; + +/* Set the BSSID Hotlist */ +wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, + wifi_bssid_hotlist_params params, + wifi_hotlist_ap_found_handler handler); + +/* Clear the BSSID Hotlist */ +wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface); + +/* SSID Hotlist */ +typedef struct { + void (*on_hotlist_ssid_found)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); + void (*on_hotlist_ssid_lost)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); +} wifi_hotlist_ssid_handler; + +typedef struct { + char ssid[32 + 1]; // SSID + wifi_band band; // band for this set of threshold params + wifi_rssi low; // low threshold + wifi_rssi high; // high threshold +} ssid_threshold_param; + +typedef struct { + int lost_ssid_sample_size; + int num_ssid; // number of hotlist SSIDs + ssid_threshold_param ssid[MAX_HOTLIST_SSID]; // hotlist SSIDs +} wifi_ssid_hotlist_params; + +/* Significant wifi change */ +typedef struct { + mac_addr bssid; // BSSID + wifi_channel channel; // channel frequency in MHz + int num_rssi; // number of rssi samples + wifi_rssi rssi[]; // RSSI history in db +} wifi_significant_change_result; + +typedef struct { + void (*on_significant_change)(wifi_request_id id, unsigned num_results, + wifi_significant_change_result** results); +} wifi_significant_change_handler; + +// The sample size parameters in the wifi_significant_change_params structure +// represent the number of occurence of a g-scan where the BSSID was seen and RSSI was +// collected for that BSSID, or, the BSSID was expected to be seen and didn't. +// for instance: lost_ap_sample_size : number of time a g-scan was performed on the +// channel the BSSID was seen last, and the BSSID was not seen during those g-scans +typedef struct { + int rssi_sample_size; // number of samples for averaging RSSI + int lost_ap_sample_size; // number of samples to confirm AP loss + int min_breaching; // number of APs breaching threshold + int num_bssid; // max 64 + ap_threshold_param ap[MAX_SIGNIFICANT_CHANGE_APS]; +} wifi_significant_change_params; + +/* Set the Signifcant AP change list */ +wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_significant_change_params params, + wifi_significant_change_handler handler); + +/* Clear the Signifcant AP change list */ +wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface); + +/* Random MAC OUI for PNO */ +wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui); + +// Enhanced PNO: +// Enhanced PNO feature is expected to be enabled all of the time (e.g. screen lit) and may thus +// require firmware to store a large number of networks, covering the whole list of known networks. +// Therefore, it is acceptable for firmware to store a crc24, crc32 or other short hash of the SSID, +// such that a low but non-zero probability of collision exist. With that scheme it should be +// possible for firmware to keep an entry as small as 4 bytes for each pno network. +// For instance, a firmware pn0 entry can be implemented in the form of: +// PNO ENTRY = crc24(3 bytes) | flags>>3 (5 bits) | auth flags(3 bits) +// +// No scans should be automatically performed by the chip. Instead all scan results from gscan +// should be scored and the wifi_epno_handler on_network_found callback should be called with +// the scan results. +// +// A PNO network shall be reported once, that is, once a network is reported by firmware +// its entry shall be marked as "done" until framework calls wifi_set_epno_list again. +// Calling wifi_set_epno_list shall reset the "done" status of pno networks in firmware. +// +// A network should only be considered found if its RSSI is above the minimum RSSI for its +// frequency range (min5GHz_rssi and min24GHz_rssi for 5GHz and 2.4GHz networks respectively). +// When disconnected the list of scan results should be returned if any network is found. +// When connected the scan results shall be reported only if the score of any network in the scan +// is greater than that of the currently connected BSSID. +// +// The FW should calculate the score of all the candidates (including currently connected one) +// with following equation: +// RSSI score = (RSSI + 85) * 4; +// If RSSI score > initial_score_max , RSSI score = initial_score_max; +// final score = RSSI score +// + current_connection_bonus (if currently connected BSSID) +// + same_network_bonus (if network has SAME_NETWORK flag) +// + secure_bonus (if the network is not open) +// + band5GHz_bonus (if BSSID is on 5G) +// If there is a BSSID’s score > current BSSID’s score, then report the cached scan results +// at the end of the scan (excluding the ones on blacklist) to the upper layer. +// Additionally, all BSSIDs that are in the BSSID blacklist should be ignored by Enhanced PNO + +// Whether directed scan needs to be performed (for hidden SSIDs) +#define WIFI_PNO_FLAG_DIRECTED_SCAN (1 << 0) +// Whether PNO event shall be triggered if the network is found on A band +#define WIFI_PNO_FLAG_A_BAND (1 << 1) +// Whether PNO event shall be triggered if the network is found on G band +#define WIFI_PNO_FLAG_G_BAND (1 << 2) +// Whether strict matching is required +// If required then the firmware must store the network's SSID and not just a hash +#define WIFI_PNO_FLAG_STRICT_MATCH (1 << 3) +// If this SSID should be considered the same network as the currently connected one for scoring +#define WIFI_PNO_FLAG_SAME_NETWORK (1 << 4) + +// Code for matching the beacon AUTH IE - additional codes TBD +#define WIFI_PNO_AUTH_CODE_OPEN (1 << 0) // open +#define WIFI_PNO_AUTH_CODE_PSK (1 << 1) // WPA_PSK or WPA2PSK +#define WIFI_PNO_AUTH_CODE_EAPOL (1 << 2) // any EAPOL + +typedef struct { + char ssid[32 + 1]; // null terminated + byte flags; // WIFI_PNO_FLAG_XXX + byte auth_bit_field; // auth bit field for matching WPA IE +} wifi_epno_network; + +/* ePNO Parameters */ +typedef struct { + int min5GHz_rssi; // minimum 5GHz RSSI for a BSSID to be considered + int min24GHz_rssi; // minimum 2.4GHz RSSI for a BSSID to be considered + int initial_score_max; // the maximum score that a network can have before bonuses + int current_connection_bonus; // only report when there is a network's score this much higher + // than the current connection. + int same_network_bonus; // score bonus for all networks with the same network flag + int secure_bonus; // score bonus for networks that are not open + int band5GHz_bonus; // 5GHz RSSI score bonus (applied to all 5GHz networks) + int num_networks; // number of wifi_epno_network objects + wifi_epno_network networks[MAX_EPNO_NETWORKS]; // PNO networks +} wifi_epno_params; + +typedef struct { + // on results + void (*on_network_found)(wifi_request_id id, unsigned num_results, wifi_scan_result* results); +} wifi_epno_handler; + +/* Set the ePNO list - enable ePNO with the given parameters */ +wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface, + const wifi_epno_params* epno_params, wifi_epno_handler handler); + +/* Reset the ePNO list - no ePNO networks should be matched after this */ +wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface); + +typedef struct { + int id; // identifier of this network block, report this in event + char realm[256]; // null terminated UTF8 encoded realm, 0 if unspecified + int64_t roamingConsortiumIds[16]; // roaming consortium ids to match, 0s if unspecified + byte plmn[3]; // mcc/mnc combination as per rules, 0s if unspecified +} wifi_passpoint_network; + +typedef struct { + void (*on_passpoint_network_found)( + wifi_request_id id, + int net_id, // network block identifier for the matched network + wifi_scan_result* result, // scan result, with channel and beacon information + int anqp_len, // length of ANQP blob + byte* anqp // ANQP data, in the information_element format + ); +} wifi_passpoint_event_handler; + +/* Sets a list for passpoint networks for PNO purposes; it should be matched + * against any passpoint networks (designated by Interworking element) found + * during regular PNO scan. */ +wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, + wifi_passpoint_network* networks, + wifi_passpoint_event_handler handler); + +/* Reset passpoint network list - no Passpoint networks should be matched after this */ +wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface); + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h new file mode 100644 index 0000000..7585cdf --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h @@ -0,0 +1,285 @@ +#include "wifi_hal.h"
+
+#ifndef __WIFI_HAL_STATS_H
+#define __WIFI_HAL_STATS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define STATS_MAJOR_VERSION 1
+#define STATS_MINOR_VERSION 0
+#define STATS_MICRO_VERSION 0
+
+typedef enum {
+ WIFI_DISCONNECTED = 0,
+ WIFI_AUTHENTICATING = 1,
+ WIFI_ASSOCIATING = 2,
+ WIFI_ASSOCIATED = 3,
+ WIFI_EAPOL_STARTED = 4, // if done by firmware/driver
+ WIFI_EAPOL_COMPLETED = 5, // if done by firmware/driver
+} wifi_connection_state;
+
+typedef enum {
+ WIFI_ROAMING_IDLE = 0,
+ WIFI_ROAMING_ACTIVE = 1,
+} wifi_roam_state;
+
+typedef enum {
+ WIFI_INTERFACE_STA = 0,
+ WIFI_INTERFACE_SOFTAP = 1,
+ WIFI_INTERFACE_IBSS = 2,
+ WIFI_INTERFACE_P2P_CLIENT = 3,
+ WIFI_INTERFACE_P2P_GO = 4,
+ WIFI_INTERFACE_NAN = 5,
+ WIFI_INTERFACE_MESH = 6,
+ WIFI_INTERFACE_TDLS = 7,
+ WIFI_INTERFACE_UNKNOWN = -1
+} wifi_interface_mode;
+
+#define WIFI_CAPABILITY_QOS 0x00000001 // set for QOS association
+#define WIFI_CAPABILITY_PROTECTED \
+ 0x00000002 // set for protected association (802.11 beacon frame control protected bit set)
+#define WIFI_CAPABILITY_INTERWORKING \
+ 0x00000004 // set if 802.11 Extended Capabilities element interworking bit is set
+#define WIFI_CAPABILITY_HS20 0x00000008 // set for HS20 association
+#define WIFI_CAPABILITY_SSID_UTF8 \
+ 0x00000010 // set is 802.11 Extended Capabilities element UTF-8 SSID bit is set
+#define WIFI_CAPABILITY_COUNTRY 0x00000020 // set is 802.11 Country Element is present
+
+typedef struct {
+ wifi_interface_mode mode; // interface mode
+ u8 mac_addr[6]; // interface mac address (self)
+ wifi_connection_state state; // connection state (valid for STA, CLI only)
+ wifi_roam_state roaming; // roaming state
+ u32 capabilities; // WIFI_CAPABILITY_XXX (self)
+ u8 ssid[33]; // null terminated SSID
+ u8 bssid[6]; // bssid
+ u8 ap_country_str[3]; // country string advertised by AP
+ u8 country_str[3]; // country string for this association
+ u8 time_slicing_duty_cycle_percent; // if this iface is being served using time slicing on a
+ // radio with one or more ifaces (i.e MCC), then the duty
+ // cycle assigned to this iface in %. If not using time
+ // slicing (i.e SCC or DBS), set to 100.
+} wifi_interface_link_layer_info;
+
+/* channel information */
+typedef struct {
+ wifi_channel_width width; // channel width (20, 40, 80, 80+80, 160, 320)
+ wifi_channel center_freq; // primary 20 MHz channel
+ wifi_channel center_freq0; // center frequency (MHz) first segment
+ wifi_channel center_freq1; // center frequency (MHz) second segment
+} wifi_channel_info;
+
+/* wifi rate */
+typedef struct {
+ u32 preamble : 3; // 0: OFDM, 1:CCK, 2:HT 3:VHT 4:HE 5:EHT 6..7 reserved
+ u32 nss : 2; // 0:1x1, 1:2x2, 3:3x3, 4:4x4
+ u32 bw : 3; // 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz 4:320Mhz
+ u32 rateMcsIdx : 8; // OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+ // HT/VHT/HE/EHT it would be mcs index
+ u32 reserved : 16; // reserved
+ u32 bitrate; // units of 100 Kbps
+} wifi_rate;
+
+/* channel statistics */
+typedef struct {
+ wifi_channel_info channel; // channel
+ u32 on_time; // msecs the radio is awake (32 bits number accruing over time)
+ u32 cca_busy_time; // msecs the CCA register is busy (32 bits number accruing over time)
+} wifi_channel_stat;
+
+// Max number of tx power levels. The actual number vary per device and is specified by
+// |num_tx_levels|
+#define RADIO_STAT_MAX_TX_LEVELS 256
+
+/* radio statistics */
+typedef struct {
+ wifi_radio radio; // wifi radio (if multiple radio supported)
+ u32 on_time; // msecs the radio is awake (32 bits number accruing over time)
+ u32 tx_time; // msecs the radio is transmitting (32 bits number accruing over time)
+ u32 num_tx_levels; // number of radio transmit power levels
+ u32* tx_time_per_levels; // pointer to an array of radio transmit per power levels in
+ // msecs accured over time
+ u32 rx_time; // msecs the radio is in active receive (32 bits number accruing over time)
+ u32 on_time_scan; // msecs the radio is awake due to all scan (32 bits number accruing over
+ // time)
+ u32 on_time_nbd; // msecs the radio is awake due to NAN (32 bits number accruing over time)
+ u32 on_time_gscan; // msecs the radio is awake due to G?scan (32 bits number accruing over
+ // time)
+ u32 on_time_roam_scan; // msecs the radio is awake due to roam?scan (32 bits number accruing
+ // over time)
+ u32 on_time_pno_scan; // msecs the radio is awake due to PNO scan (32 bits number accruing over
+ // time)
+ u32 on_time_hs20; // msecs the radio is awake due to HS2.0 scans and GAS exchange (32 bits
+ // number accruing over time)
+ u32 num_channels; // number of channels
+ wifi_channel_stat channels[]; // channel statistics
+} wifi_radio_stat;
+
+/**
+ * Packet statistics reporting by firmware is performed on MPDU basi (i.e. counters increase by 1
+ * for each MPDU) As well, "data packet" in associated comments, shall be interpreted as 802.11 data
+ * packet, that is, 802.11 frame control subtype == 2 and excluding management and control frames.
+ *
+ * As an example, in the case of transmission of an MSDU fragmented in 16 MPDUs which are
+ * transmitted OTA in a 16 units long a-mpdu, for which a block ack is received with 5 bits set:
+ * tx_mpdu : shall increase by 5
+ * retries : shall increase by 16
+ * tx_ampdu : shall increase by 1
+ * data packet counters shall not increase regardless of the number of BAR potentially sent by
+ * device for this a-mpdu data packet counters shall not increase regardless of the number of BA
+ * received by device for this a-mpdu
+ *
+ * For each subsequent retransmission of the 11 remaining non ACK'ed mpdus
+ * (regardless of the fact that they are transmitted in a-mpdu or not)
+ * retries : shall increase by 1
+ *
+ * If no subsequent BA or ACK are received from AP, until packet lifetime expires for those 11
+ * packet that were not ACK'ed mpdu_lost : shall increase by 11
+ */
+
+/* per rate statistics */
+typedef struct {
+ wifi_rate rate; // rate information
+ u32 tx_mpdu; // number of successfully transmitted data pkts (ACK rcvd)
+ u32 rx_mpdu; // number of received data pkts
+ u32 mpdu_lost; // number of data packet losses (no ACK)
+ u32 retries; // total number of data pkt retries
+ u32 retries_short; // number of short data pkt retries
+ u32 retries_long; // number of long data pkt retries
+} wifi_rate_stat;
+
+/* access categories */
+typedef enum {
+ WIFI_AC_VO = 0,
+ WIFI_AC_VI = 1,
+ WIFI_AC_BE = 2,
+ WIFI_AC_BK = 3,
+ WIFI_AC_MAX = 4,
+} wifi_traffic_ac;
+
+/* wifi peer type */
+typedef enum {
+ WIFI_PEER_STA,
+ WIFI_PEER_AP,
+ WIFI_PEER_P2P_GO,
+ WIFI_PEER_P2P_CLIENT,
+ WIFI_PEER_NAN,
+ WIFI_PEER_TDLS,
+ WIFI_PEER_INVALID,
+} wifi_peer_type;
+
+/* per peer statistics */
+typedef struct bssload_info {
+ u16 sta_count; // station count
+ u16 chan_util; // channel utilization
+ u8 PAD[4];
+} bssload_info_t;
+
+typedef struct {
+ wifi_peer_type type; // peer type (AP, TDLS, GO etc.)
+ u8 peer_mac_address[6]; // mac address
+ u32 capabilities; // peer WIFI_CAPABILITY_XXX
+ bssload_info_t bssload; // STA count and CU
+ u32 num_rate; // number of rates
+ wifi_rate_stat rate_stats[]; // per rate statistics, number of entries = num_rate
+} wifi_peer_info;
+
+/* Per access category statistics */
+typedef struct {
+ wifi_traffic_ac ac; // access category (VI, VO, BE, BK)
+ u32 tx_mpdu; // number of successfully transmitted unicast data pkts (ACK rcvd)
+ u32 rx_mpdu; // number of received unicast data packets
+ u32 tx_mcast; // number of succesfully transmitted multicast data packets
+ // STA case: implies ACK received from AP for the unicast packet in which mcast
+ // pkt was sent
+ u32 rx_mcast; // number of received multicast data packets
+ u32 rx_ampdu; // number of received unicast a-mpdus; support of this counter is optional
+ u32 tx_ampdu; // number of transmitted unicast a-mpdus; support of this counter is optional
+ u32 mpdu_lost; // number of data pkt losses (no ACK)
+ u32 retries; // total number of data pkt retries
+ u32 retries_short; // number of short data pkt retries
+ u32 retries_long; // number of long data pkt retries
+ u32 contention_time_min; // data pkt min contention time (usecs)
+ u32 contention_time_max; // data pkt max contention time (usecs)
+ u32 contention_time_avg; // data pkt avg contention time (usecs)
+ u32 contention_num_samples; // num of data pkts used for contention statistics
+} wifi_wmm_ac_stat;
+
+/* interface statistics */
+typedef struct {
+ wifi_interface_handle iface; // wifi interface
+ wifi_interface_link_layer_info info; // current state of the interface
+ u32 beacon_rx; // access point beacon received count from connected AP
+ u64 average_tsf_offset; // average beacon offset encountered (beacon_TSF - TBTT)
+ // The average_tsf_offset field is used so as to calculate the
+ // typical beacon contention time on the channel as well may be
+ // used to debug beacon synchronization and related power consumption
+ // issue
+ u32 leaky_ap_detected; // indicate that this AP typically leaks packets beyond the driver guard
+ // time.
+ u32 leaky_ap_avg_num_frames_leaked; // average number of frame leaked by AP after frame with PM
+ // bit set was ACK'ed by AP
+ u32 leaky_ap_guard_time; // guard time currently in force (when implementing IEEE power
+ // management based on frame control PM bit), How long driver waits
+ // before shutting down the radio and after receiving an ACK for a
+ // data frame with PM bit set)
+ u32 mgmt_rx; // access point mgmt frames received count from connected AP (including Beacon)
+ u32 mgmt_action_rx; // action frames received count
+ u32 mgmt_action_tx; // action frames transmit count
+ wifi_rssi rssi_mgmt; // access Point Beacon and Management frames RSSI (averaged)
+ wifi_rssi rssi_data; // access Point Data Frames RSSI (averaged) from connected AP
+ wifi_rssi rssi_ack; // access Point ACK RSSI (averaged) from connected AP
+ wifi_wmm_ac_stat ac[WIFI_AC_MAX]; // per ac data packet statistics
+ u32 num_peers; // number of peers
+ wifi_peer_info peer_info[]; // per peer statistics
+} wifi_iface_stat;
+
+/* configuration params */
+typedef struct {
+ u32 mpdu_size_threshold; // threshold to classify the pkts as short or long
+ // packet size < mpdu_size_threshold => short
+ u32 aggressive_statistics_gathering; // set for field debug mode. Driver should collect all
+ // statistics regardless of performance impact.
+} wifi_link_layer_params;
+
+/* API to trigger the link layer statistics collection.
+ Unless his API is invoked - link layer statistics will not be collected.
+ Radio statistics (once started) do not stop or get reset unless wifi_clear_link_stats is invoked
+ Interface statistics (once started) reset and start afresh after each connection */
+wifi_error wifi_set_link_stats(wifi_interface_handle iface, wifi_link_layer_params params);
+
+/* callback for reporting link layer stats */
+typedef struct {
+ void (*on_link_stats_results)(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios,
+ wifi_radio_stat* radio_stat);
+} wifi_stats_result_handler;
+
+/* api to collect the link layer statistics for a given iface and all the radio stats */
+wifi_error wifi_get_link_stats(wifi_request_id id, wifi_interface_handle iface,
+ wifi_stats_result_handler handler);
+
+/* wifi statistics bitmap */
+#define WIFI_STATS_RADIO 0x00000001 // all radio statistics
+#define WIFI_STATS_RADIO_CCA 0x00000002 // cca_busy_time (within radio statistics)
+#define WIFI_STATS_RADIO_CHANNELS 0x00000004 // all channel statistics (within radio statistics)
+#define WIFI_STATS_RADIO_SCAN 0x00000008 // all scan statistics (within radio statistics)
+#define WIFI_STATS_IFACE 0x00000010 // all interface statistics
+#define WIFI_STATS_IFACE_TXRATE 0x00000020 // all tx rate statistics (within interface statistics)
+#define WIFI_STATS_IFACE_AC 0x00000040 // all ac statistics (within interface statistics)
+#define WIFI_STATS_IFACE_CONTENTION \
+ 0x00000080 // all contention (min, max, avg) statistics (within ac statisctics)
+
+/* clear api to reset statistics, stats_clear_rsp_mask identifies what stats have been cleared
+ stop_req = 1 will imply whether to stop the statistics collection.
+ stop_rsp = 1 will imply that stop_req was honored and statistics collection was stopped.
+ */
+wifi_error wifi_clear_link_stats(wifi_interface_handle iface, u32 stats_clear_req_mask,
+ u32* stats_clear_rsp_mask, u8 stop_req, u8* stop_rsp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /*__WIFI_HAL_STATS_ */
diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h new file mode 100644 index 0000000..2b6d12a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008 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 _HARDWARE_POWER_H +#define _HARDWARE_POWER_H + +#include <stdint.h> + +#if __cplusplus +extern "C" { +#endif + +enum { + PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off + FULL_WAKE_LOCK = 2 // the screen is also on +}; + +// while you have a lock held, the device will stay on at least at the +// level you request. +int acquire_wake_lock(int lock, const char* id); +int release_wake_lock(const char* id); + +#if __cplusplus +} // extern "C" +#endif + +#endif // _HARDWARE_POWER_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h new file mode 100644 index 0000000..3369e3e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h @@ -0,0 +1,57 @@ +/* + * 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_HAL_ROAM_H__ +#define __WIFI_HAL_ROAM_H__ + +#include "wifi_hal.h" + +#define MAX_BLACKLIST_BSSID 16 +#define MAX_WHITELIST_SSID 8 +#define MAX_SSID_LENGTH 32 + +typedef struct { + u32 max_blacklist_size; + u32 max_whitelist_size; +} wifi_roaming_capabilities; + +typedef enum { ROAMING_DISABLE, ROAMING_ENABLE } fw_roaming_state_t; + +typedef struct { + u32 length; + char ssid_str[MAX_SSID_LENGTH]; +} ssid_t; + +typedef struct { + u32 num_blacklist_bssid; // Number of bssids valid in blacklist_bssid[]. + mac_addr blacklist_bssid[MAX_BLACKLIST_BSSID]; // List of bssids which should not be considered + // for romaing by firmware/driver. + u32 num_whitelist_ssid; // Number of ssids valid in whitelist_ssid[]. + ssid_t whitelist_ssid[MAX_WHITELIST_SSID]; // List of ssids to which firmware/driver can + // consider to roam to. +} wifi_roaming_config; + +/* Get the chipset roaming capabilities. */ +wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle, + wifi_roaming_capabilities* caps); +/* Enable/disable firmware roaming */ +wifi_error wifi_enable_firmware_roaming(wifi_interface_handle handle, fw_roaming_state_t state); + +/* Pass down the blacklist BSSID and whitelist SSID to firmware. */ +wifi_error wifi_configure_roaming(wifi_interface_handle handle, + wifi_roaming_config* roaming_config); + +#endif /* __WIFI_HAL_ROAM_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h new file mode 100644 index 0000000..8be7fd3 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h @@ -0,0 +1,314 @@ + +#include "gscan.h" +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_RTT_H__ +#define __WIFI_HAL_RTT_H__ + +/* Ranging status */ +typedef enum { + RTT_STATUS_SUCCESS = 0, + RTT_STATUS_FAILURE = 1, // general failure status + RTT_STATUS_FAIL_NO_RSP = 2, // target STA does not respond to request + RTT_STATUS_FAIL_REJECTED = 3, // request rejected. Applies to 2-sided RTT only + RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4, + RTT_STATUS_FAIL_TM_TIMEOUT = 5, // timing measurement times out + RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6, // Target on different channel, cannot range + RTT_STATUS_FAIL_NO_CAPABILITY = 7, // ranging not supported + RTT_STATUS_ABORTED = 8, // request aborted for unknown reason + RTT_STATUS_FAIL_INVALID_TS = 9, // Invalid T1-T4 timestamp + RTT_STATUS_FAIL_PROTOCOL = 10, // 11mc protocol failed + RTT_STATUS_FAIL_SCHEDULE = 11, // request could not be scheduled + RTT_STATUS_FAIL_BUSY_TRY_LATER = 12, // responder cannot collaborate at time of request + RTT_STATUS_INVALID_REQ = 13, // bad request args + RTT_STATUS_NO_WIFI = 14, // WiFi not enabled + RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = + 15, // Responder overrides param info, cannot range with new params + RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE = 16, // Negotiation failure + RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17, // concurrency not supported (NDP+RTT) +} wifi_rtt_status; + +/* RTT peer type */ +typedef enum { + RTT_PEER_AP = 0x1, + RTT_PEER_STA = 0x2, + RTT_PEER_P2P_GO = 0x3, + RTT_PEER_P2P_CLIENT = 0x4, + RTT_PEER_NAN = 0x5 +} rtt_peer_type; + +/* RTT Measurement Bandwidth */ +typedef enum { + WIFI_RTT_BW_5 = 0x01, + WIFI_RTT_BW_10 = 0x02, + WIFI_RTT_BW_20 = 0x04, + WIFI_RTT_BW_40 = 0x08, + WIFI_RTT_BW_80 = 0x10, + WIFI_RTT_BW_160 = 0x20, + WIFI_RTT_BW_320 = 0x40 +} wifi_rtt_bw; + +/* RTT Measurement Preamble */ +typedef enum { + WIFI_RTT_PREAMBLE_LEGACY = 0x1, + WIFI_RTT_PREAMBLE_HT = 0x2, + WIFI_RTT_PREAMBLE_VHT = 0x4, + WIFI_RTT_PREAMBLE_HE = 0x8, + WIFI_RTT_PREAMBLE_EHT = 0x10, +} wifi_rtt_preamble; + +/* RTT Type */ +typedef enum { + RTT_TYPE_1_SIDED = 0x1, + RTT_TYPE_2_SIDED = 0x2, +} wifi_rtt_type; + +/* RTT configuration */ +typedef struct { + mac_addr addr; // peer device mac address + wifi_rtt_type type; // 1-sided or 2-sided RTT + rtt_peer_type peer; // optional - peer device hint (STA, P2P, AP) + wifi_channel_info channel; // Required for STA-AP mode, optional for P2P, NBD etc. + unsigned burst_period; // Time interval between bursts (units: 100 ms). + // Applies to 1-sided and 2-sided RTT multi-burst requests. + // Range: 0-31, 0: no preference by initiator (2-sided RTT) + unsigned num_burst; // Total number of RTT bursts to be executed. It will be + // specified in the same way as the parameter "Number of + // Burst Exponent" found in the FTM frame format. It + // applies to both: 1-sided RTT and 2-sided RTT. Valid + // values are 0 to 15 as defined in 802.11mc std. + // 0 means single shot + // The implication of this parameter on the maximum + // number of RTT results is the following: + // for 1-sided RTT: max num of RTT results = + // (2^num_burst)*(num_frames_per_burst) for 2-sided RTT: max num of RTT + // results = (2^num_burst)*(num_frames_per_burst - 1) + unsigned num_frames_per_burst; // num of frames per burst. + // Minimum value = 1, Maximum value = 31 + // For 2-sided this equals the number of FTM frames + // to be attempted in a single burst. This also + // equals the number of FTM frames that the + // initiator will request that the responder send + // in a single frame. + unsigned + num_retries_per_rtt_frame; // number of retries for a failed RTT frame. Applies + // to 1-sided RTT only. Minimum value = 0, Maximum value = 3 + + // following fields are only valid for 2-side RTT + unsigned num_retries_per_ftmr; // Maximum number of retries that the initiator can + // retry an FTMR frame. + // Minimum value = 0, Maximum value = 3 + byte LCI_request; // 1: request LCI, 0: do not request LCI + byte LCR_request; // 1: request LCR, 0: do not request LCR + unsigned burst_duration; // Applies to 1-sided and 2-sided RTT. Valid values will + // be 2-11 and 15 as specified by the 802.11mc std for + // the FTM parameter burst duration. In a multi-burst + // request, if responder overrides with larger value, + // the initiator will return failure. In a single-burst + // request if responder overrides with larger value, + // the initiator will sent TMR_STOP to terminate RTT + // at the end of the burst_duration it requested. + wifi_rtt_preamble preamble; // RTT preamble to be used in the RTT frames + wifi_rtt_bw bw; // RTT BW to be used in the RTT frames +} wifi_rtt_config; + +/* RTT results */ +typedef struct { + mac_addr addr; // device mac address + unsigned burst_num; // burst number in a multi-burst request + unsigned measurement_number; // Total RTT measurement frames attempted + unsigned success_number; // Total successful RTT measurement frames + byte number_per_burst_peer; // Maximum number of "FTM frames per burst" supported by + // the responder STA. Applies to 2-sided RTT only. + // If reponder overrides with larger value: + // - for single-burst request initiator will truncate the + // larger value and send a TMR_STOP after receiving as + // many frames as originally requested. + // - for multi-burst request, initiator will return + // failure right away. + wifi_rtt_status status; // ranging status + byte retry_after_duration; // When status == RTT_STATUS_FAIL_BUSY_TRY_LATER, + // this will be the time provided by the responder as to + // when the request can be tried again. Applies to 2-sided + // RTT only. In sec, 1-31sec. + wifi_rtt_type type; // RTT type + wifi_rssi rssi; // average rssi in 0.5 dB steps e.g. 143 implies -71.5 dB + wifi_rssi rssi_spread; // rssi spread in 0.5 dB steps e.g. 5 implies 2.5 dB spread (optional) + wifi_rate tx_rate; // 1-sided RTT: TX rate of RTT frame. + // 2-sided RTT: TX rate of initiator's Ack in response to FTM frame. + wifi_rate rx_rate; // 1-sided RTT: TX rate of Ack from other side. + // 2-sided RTT: TX rate of FTM frame coming from responder. + wifi_timespan rtt; // round trip time in picoseconds + wifi_timespan rtt_sd; // rtt standard deviation in picoseconds + wifi_timespan rtt_spread; // difference between max and min rtt times recorded in picoseconds + int distance_mm; // distance in mm (optional) + int distance_sd_mm; // standard deviation in mm (optional) + int distance_spread_mm; // difference between max and min distance recorded in mm (optional) + wifi_timestamp ts; // time of the measurement (in microseconds since boot) + int burst_duration; // in ms, actual time taken by the FW to finish one burst + // measurement. Applies to 1-sided and 2-sided RTT. + int negotiated_burst_num; // Number of bursts allowed by the responder. Applies + // to 2-sided RTT only. + wifi_information_element* LCI; // for 11mc only + wifi_information_element* LCR; // for 11mc only +} wifi_rtt_result; + +/* RTT result callback */ +typedef struct { + void (*on_rtt_results)(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_result[]); +} wifi_rtt_event_handler; + +/* API to request RTT measurement */ +wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, + unsigned num_rtt_config, wifi_rtt_config rtt_config[], + wifi_rtt_event_handler handler); + +/* API to cancel RTT measurements */ +wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, + unsigned num_devices, mac_addr addr[]); + +/* NBD ranging channel map */ +typedef struct { + wifi_channel availablity[32]; // specifies the channel map for each of the 16 TU windows + // frequency of 0 => unspecified; which means firmware is + // free to do whatever it wants in this window. +} wifi_channel_map; + +/* API to start publishing the channel map on responder device in a NBD cluster. + Responder device will take this request and schedule broadcasting the channel map + in a NBD ranging attribute in a SDF. DE will automatically remove the ranging + attribute from the OTA queue after number of DW specified by num_dw + where Each DW is 512 TUs apart */ +wifi_error wifi_rtt_channel_map_set(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_map* params, unsigned num_dw); + +/* API to clear the channel map on the responder device in a NBD cluster. + Responder device will cancel future ranging channel request, starting from next + DW interval and will also stop broadcasting NBD ranging attribute in SDF */ +wifi_error wifi_rtt_channel_map_clear(wifi_request_id id, wifi_interface_handle iface); + +// Preamble definition for bit mask used in wifi_rtt_capabilities +#define PREAMBLE_LEGACY 0x1 +#define PREAMBLE_HT 0x2 +#define PREAMBLE_VHT 0x4 +#define PREAMBLE_HE 0x8 +#define PREAMBLE_EHT 0x10 + +// BW definition for bit mask used in wifi_rtt_capabilities +#define BW_5_SUPPORT 0x1 +#define BW_10_SUPPORT 0x2 +#define BW_20_SUPPORT 0x4 +#define BW_40_SUPPORT 0x8 +#define BW_80_SUPPORT 0x10 +#define BW_160_SUPPORT 0x20 +#define BW_320_SUPPORT 0x40 + +/* RTT Capabilities */ +typedef struct { + byte rtt_one_sided_supported; // if 1-sided rtt data collection is supported + byte rtt_ftm_supported; // if ftm rtt data collection is supported + byte lci_support; // if initiator supports LCI request. Applies to 2-sided RTT + byte lcr_support; // if initiator supports LCR request. Applies to 2-sided RTT + byte preamble_support; // bit mask indicates what preamble is supported by initiator + byte bw_support; // bit mask indicates what BW is supported by initiator + byte responder_supported; // if 11mc responder mode is supported + byte mc_version; // draft 11mc spec version supported by chip. For instance, + // version 4.0 should be 40 and version 4.3 should be 43 etc. +} wifi_rtt_capabilities; + +/* RTT capabilities of the device */ +wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, + wifi_rtt_capabilities* capabilities); + +/* debugging definitions */ +enum { + RTT_DEBUG_DISABLE, + RTT_DEBUG_LOG, + RTT_DEBUG_PROTO, + RTT_DEBUG_BURST, + RTT_DEBUG_ACCURACY, + RTT_DEBUG_LOGDETAIL +}; // rtt debug type + +enum { RTT_DEBUG_FORMAT_TXT, RTT_DEBUG_FORMAT_BINARY }; // rtt debug format + +typedef struct rtt_debug { + unsigned version; + unsigned len; // total length of after len field + unsigned type; // rtt debug type + unsigned format; // rtt debug format + char dbuf[0]; // debug content +} rtt_debug_t; + +/* set configuration for debug */ +wifi_error wifi_rtt_debug_cfg(wifi_interface_handle h, unsigned rtt_dbg_type, char* cfgbuf, + unsigned cfg_buf_size); +/* get the debug information */ +wifi_error wifi_rtt_debug_get(wifi_interface_handle h, rtt_debug_t** debugbuf); +/* free the debug buffer */ +wifi_error wifi_rtt_debug_free(wifi_interface_handle h, rtt_debug_t* debugbuf); + +/* API for setting LCI/LCR information to be provided to a requestor */ +typedef enum { + WIFI_MOTION_NOT_EXPECTED = 0, // Not expected to change location + WIFI_MOTION_EXPECTED = 1, // Expected to change location + WIFI_MOTION_UNKNOWN = 2, // Movement pattern unknown +} wifi_motion_pattern; + +typedef struct { + long latitude; // latitude in degrees * 2^25 , 2's complement + long longitude; // latitude in degrees * 2^25 , 2's complement + int altitude; // Altitude in units of 1/256 m + byte latitude_unc; // As defined in Section 2.3.2 of IETF RFC 6225 + byte longitude_unc; // As defined in Section 2.3.2 of IETF RFC 6225 + byte altitude_unc; // As defined in Section 2.4.5 from IETF RFC 6225: + + // Following element for configuring the Z subelement + wifi_motion_pattern motion_pattern; + int floor; // floor in units of 1/16th of floor. 0x80000000 if unknown. + int height_above_floor; // in units of 1/64 m + int height_unc; // in units of 1/64 m. 0 if unknown +} wifi_lci_information; + +typedef struct { + char country_code[2]; // country code + int length; // length of the info field + char civic_info[256]; // Civic info to be copied in FTM frame +} wifi_lcr_information; + +// API to configure the LCI. Used in RTT Responder mode only +wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface, wifi_lci_information* lci); + +// API to configure the LCR. Used in RTT Responder mode only. +wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface, wifi_lcr_information* lcr); + +/** + * RTT Responder information + */ +typedef struct { + wifi_channel_info channel; + wifi_rtt_preamble preamble; +} wifi_rtt_responder; + +/** + * Get RTT responder information e.g. WiFi channel to enable responder on. + */ +wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface, + wifi_rtt_responder* responder_info); + +/** + * Enable RTT responder mode. + * channel_hint - hint of the channel information where RTT responder should be enabled on. + * max_duration_seconds - timeout of responder mode. + * channel_used - channel used for RTT responder, NULL if responder is not enabled. + */ +wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_info channel_hint, unsigned max_duration_seconds, + wifi_rtt_responder* responder_info); + +/** + * Disable RTT responder mode. + */ +wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface); + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h new file mode 100644 index 0000000..787b13a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h @@ -0,0 +1,84 @@ + +#include "wifi_hal.h" + +#ifndef _TDLS_H_ +#define _TDLS_H_ + +typedef enum { + WIFI_TDLS_DISABLED = 1, /* TDLS is not enabled, default status for all STAs */ + WIFI_TDLS_ENABLED, /* TDLS is enabled, but not yet tried */ + WIFI_TDLS_ESTABLISHED, /* Direct link is established */ + WIFI_TDLS_ESTABLISHED_OFF_CHANNEL, /* Direct link is established using MCC */ + WIFI_TDLS_DROPPED, /* Direct link was established, + * but is temporarily dropped now */ + WIFI_TDLS_FAILED /* TDLS permanent failed. Inform error to upper layer + * and go back to WIFI_TDLS_DISABLED */ +} wifi_tdls_state; + +typedef enum { + WIFI_TDLS_SUCCESS, /* Success */ + WIFI_TDLS_UNSPECIFIED = -1, /* Unspecified reason */ + WIFI_TDLS_NOT_SUPPORTED = -2, /* Remote side doesn't support TDLS */ + WIFI_TDLS_UNSUPPORTED_BAND = -3, /* Remote side doesn't support this band */ + WIFI_TDLS_NOT_BENEFICIAL = -4, /* Going to AP is better than going direct */ + WIFI_TDLS_DROPPED_BY_REMOTE = -5 /* Remote side doesn't want it anymore */ +} wifi_tdls_reason; + +typedef struct { + int channel; /* channel hint, in channel number (NOT frequency ) */ + int global_operating_class; /* operating class to use */ + int max_latency_ms; /* max latency that can be tolerated by apps */ + int min_bandwidth_kbps; /* bandwidth required by apps, in kilo bits per second */ +} wifi_tdls_params; + +typedef struct { + int channel; + int global_operating_class; + wifi_tdls_state state; + wifi_tdls_reason reason; +} wifi_tdls_status; + +typedef struct { + int max_concurrent_tdls_session_num; /* Maximum TDLS session number can be supported by the + * Firmware and hardware*/ + int is_global_tdls_supported; /* 1 -- support, 0 -- not support */ + int is_per_mac_tdls_supported; /* 1 -- support, 0 -- not support */ + int is_off_channel_tdls_supported; /* 1 -- support, 0 -- not support */ +} wifi_tdls_capabilities; + +typedef struct { + /* on_tdls_state_changed - reports state of TDLS link to framework + * Report this event when the state of TDLS link changes */ + void (*on_tdls_state_changed)(mac_addr addr, wifi_tdls_status status); +} wifi_tdls_handler; + +/* wifi_enable_tdls - enables TDLS-auto mode for a specific route + * + * params specifies hints, which provide more information about + * why TDLS is being sought. The firmware should do its best to + * honor the hints before downgrading regular AP link + * If upper layer has no specific values, this should be NULL + * + * handler is used to inform the upper layer about the status change and the corresponding reason + */ +wifi_error wifi_enable_tdls(wifi_interface_handle iface, mac_addr addr, wifi_tdls_params* params, + wifi_tdls_handler handler); + +/* wifi_disable_tdls - disables TDLS-auto mode for a specific route + * + * This terminates any existing TDLS with addr device, and frees the + * device resources to make TDLS connections on new routes. + * + * DON'T fire any more events on 'handler' specified in earlier call to + * wifi_enable_tdls after this action. + */ +wifi_error wifi_disable_tdls(wifi_interface_handle iface, mac_addr addr); + +/* wifi_get_tdls_status - allows getting the status of TDLS for a specific route */ +wifi_error wifi_get_tdls_status(wifi_interface_handle iface, mac_addr addr, + wifi_tdls_status* status); + +/* return the current HW + Firmware combination's TDLS capabilities */ +wifi_error wifi_get_tdls_capabilities(wifi_interface_handle iface, + wifi_tdls_capabilities* capabilities); +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h new file mode 100644 index 0000000..5b82b32 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 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 _HARDWARE_UEVENT_H +#define _HARDWARE_UEVENT_H + +#if __cplusplus +extern "C" { +#endif + +int uevent_init(); +int uevent_get_fd(); +int uevent_next_event(char* buffer, int buffer_length); +int uevent_add_native_handler(void (*handler)(void* data, const char* msg, int msg_len), + void* handler_data); +int uevent_remove_native_handler(void (*handler)(void* data, const char* msg, int msg_len)); + +#if __cplusplus +} // extern "C" +#endif + +#endif // _HARDWARE_UEVENT_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h new file mode 100644 index 0000000..c7392c2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 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_CACHED_SCAN_RESULTS_H__ +#define __WIFI_CACHED_SCAN_RESULTS_H__ + +#include "wifi_hal.h" + +#define WIFI_CACHED_SCAN_RESULT_FLAGS_NONE (0) +/* Element ID 61 (HT Operation) is present (see HT 7.3.2) */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_HT_OPS_PRESENT (1 << 0) +/* Element ID 192 (VHT Operation) is present (see VHT 8.4.2) */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_VHT_OPS_PRESENT (1 << 1) +/* Element ID 255 + Extension 36 (HE Operation) is present + * (see 802.11ax 9.4.2.1) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_HE_OPS_PRESENT (1 << 2) +/* Element ID 255 + Extension 106 (HE Operation) is present + * (see 802.11be D1.5 9.4.2.1) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_EHT_OPS_PRESENT (1 << 3) +/* Element ID 127 (Extended Capabilities) is present, and bit 70 + * (Fine Timing Measurement Responder) is set to 1 + * (see IEEE Std 802.11-2016 9.4.2.27) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_IS_FTM_RESPONDER (1 << 4) + +/** + * Provides information about a single access point (AP) detected in a scan. + */ +typedef struct { + /* Number of milliseconds prior to ts in the enclosing + * wifi_cached_scan_result_report struct when + * the probe response or beacon frame that + * was used to populate this structure was received. + */ + u32 age_ms; + /* The Capability Information field */ + u16 capability; + /* null terminated */ + u8 ssid[33]; + u8 ssid_len; + u8 bssid[6]; + /* A set of flags from WIFI_CACHED_SCAN_RESULT_FLAGS_* */ + u8 flags; + s8 rssi; + wifi_channel_spec chanspec; +} wifi_cached_scan_result; + +/* + * Data structure sent with events of type WifiCachedScanResult. + */ +typedef struct { + /* time since boot (in microsecond) when the result was retrieved */ + wifi_timestamp ts; + /* If 0, indicates that all frequencies in current regulation were + * scanned. Otherwise, indicates the number of frequencies scanned, as + * specified in scanned_freq_list. + */ + u16 scanned_freq_num; + /* Pointer to an array containing scanned_freq_num values comprising the + * set of frequencies that were scanned. Frequencies are specified as + * channel center frequencies in MHz. May be NULL if scannedFreqListLen is + * 0. + */ + const u32* scanned_freq_list; + /* The total number of cached results returned. */ + u8 result_cnt; + /* Pointer to an array containing result_cnt entries. May be NULL if + * result_cnt is 0. + */ + const wifi_cached_scan_result* results; +} wifi_cached_scan_report; + +/* callback for reporting cached scan report */ +typedef struct { + void (*on_cached_scan_results)(wifi_cached_scan_report* cache_report); +} wifi_cached_scan_result_handler; +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h new file mode 100644 index 0000000..459a3fe --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h @@ -0,0 +1,44 @@ +#include "wifi_hal.h"
+
+#ifndef __WIFI_HAL_CONFIG_H
+#define __WIFI_HAL_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define CONFIG_MAJOR_VERSION 1
+#define CONFIG_MINOR_VERSION 0
+#define CONFIG_MICRO_VERSION 0
+
+// whether the wifi chipset wakes at every dtim beacon or a multiple of the dtim period
+// if extended_dtim is set to 3, the STA shall wake up every 3 DTIM beacons
+wifi_error wifi_extended_dtim_config_set(wifi_request_id id, wifi_interface_handle iface,
+ int extended_dtim);
+
+// set the country code to driver
+wifi_error wifi_set_country_code(wifi_interface_handle iface, const char* country_code);
+
+// set the wifi_iface stats averaging factor used to calculate
+// statistics like average the TSF offset or average number of frame leaked
+// For instance, upon beacon reception:
+// current_avg = ((beacon_TSF - TBTT) * factor + previous_avg * (0x10000 - factor) ) / 0x10000
+// For instance, when evaluating leaky APs:
+// current_avg = ((num frame received within guard time) * factor + previous_avg * (0x10000 -
+// factor)) / 0x10000
+
+wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor(wifi_request_id id,
+ wifi_interface_handle iface,
+ u16 factor);
+
+// configure guard time, i.e. when implementing IEEE power management based on
+// frame control PM bit, how long driver waits before shutting down the radio and
+// after receiving an ACK for a data frame with PM bit set
+wifi_error wifi_set_guard_time(wifi_request_id id, wifi_interface_handle iface, u32 guard_time);
+
+#ifdef __cplusplus
+}
+
+#endif /* __cplusplus */
+
+#endif /*__WIFI_HAL_STATS_ */
diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h new file mode 100644 index 0000000..383ba71 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h @@ -0,0 +1,1020 @@ +/* + * 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_HAL_H__ +#define __WIFI_HAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#include <stdint.h> + +#define IFNAMSIZ 16 + +/* typedefs */ +typedef unsigned char byte; +typedef unsigned char u8; +typedef signed char s8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint64_t u64; +typedef int64_t s64; +typedef int wifi_request_id; +typedef int wifi_channel; // indicates channel frequency in MHz +typedef int wifi_rssi; +typedef int wifi_radio; +typedef byte mac_addr[6]; +typedef byte oui[3]; +typedef int64_t wifi_timestamp; // In microseconds (us) +typedef int64_t wifi_timespan; // In picoseconds (ps) +typedef uint64_t feature_set; + +/* forward declarations */ +struct wifi_info; +struct wifi_interface_info; +typedef struct wifi_info* wifi_handle; +typedef struct wifi_interface_info* wifi_interface_handle; + +/* WiFi Common definitions */ +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_320 = 7, + WIFI_CHAN_WIDTH_INVALID = -1 +} wifi_channel_width; + +/* Pre selected Power scenarios to be applied from BDF file */ +typedef enum { + WIFI_POWER_SCENARIO_INVALID = -2, + WIFI_POWER_SCENARIO_DEFAULT = -1, + WIFI_POWER_SCENARIO_VOICE_CALL = 0, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF = 1, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON = 2, + WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF = 3, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON = 4, + WIFI_POWER_SCENARIO_ON_BODY_BT = 5, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT = 6, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW = 7, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT = 8, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT = 9, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT = 10, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW = 11, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW = 12, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF_UNFOLDED = 13, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON_UNFOLDED = 14, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_UNFOLDED = 15, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW_UNFOLDED = 16, + WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF_UNFOLDED = 17, + WIFI_POWER_SCENARIO_ON_BODY_BT_UNFOLDED = 18, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_UNFOLDED = 19, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT_UNFOLDED = 20, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_UNFOLDED = 21, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_UNFOLDED = 22, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW_UNFOLDED = 23, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW_UNFOLDED = 24, +} wifi_power_scenario; + +typedef enum { + WIFI_LATENCY_MODE_NORMAL = 0, + WIFI_LATENCY_MODE_LOW = 1, +} wifi_latency_mode; + +/* Wifi Thermal mitigation modes */ +typedef enum { + WIFI_MITIGATION_NONE = 0, + WIFI_MITIGATION_LIGHT = 1, + WIFI_MITIGATION_MODERATE = 2, + WIFI_MITIGATION_SEVERE = 3, + WIFI_MITIGATION_CRITICAL = 4, + WIFI_MITIGATION_EMERGENCY = 5, +} wifi_thermal_mode; + +/* + * Wifi voice over IP mode + * may add new modes later, for example, voice + video over IP mode. + */ +typedef enum { + WIFI_VOIP_MODE_OFF = 0, + WIFI_VOIP_MODE_ON = 1, +} wifi_voip_mode; + +/* List of interface types supported */ +typedef enum { + WIFI_INTERFACE_TYPE_STA = 0, + WIFI_INTERFACE_TYPE_AP = 1, + WIFI_INTERFACE_TYPE_P2P = 2, + WIFI_INTERFACE_TYPE_NAN = 3, +} wifi_interface_type; + +/* + * enum wlan_mac_band - Band information corresponding to the WLAN MAC. + */ +typedef enum { + /* WLAN MAC Operates in 2.4 GHz Band */ + WLAN_MAC_2_4_BAND = 1 << 0, + /* WLAN MAC Operates in 5 GHz Band */ + WLAN_MAC_5_0_BAND = 1 << 1, + /* WLAN MAC Operates in 6 GHz Band */ + WLAN_MAC_6_0_BAND = 1 << 2, + /* WLAN MAC Operates in 60 GHz Band */ + WLAN_MAC_60_0_BAND = 1 << 3, +} wlan_mac_band; + +/* List of chre nan rtt state */ +typedef enum { + CHRE_PREEMPTED = 0, + CHRE_UNAVAILABLE = 1, + CHRE_AVAILABLE = 2, +} chre_nan_rtt_state; + +typedef struct { + wifi_channel_width width; + int center_frequency0; + int center_frequency1; + int primary_frequency; +} wifi_channel_spec; + +/* + * wifi_usable_channel specifies a channel frequency, bandwidth, and bitmask + * of modes allowed on the channel. + */ +typedef struct { + /* Channel frequency in MHz */ + wifi_channel freq; + /* Channel operating width (20, 40, 80, 160, 320 etc.) */ + wifi_channel_width width; + /* BIT MASK of BIT(WIFI_INTERFACE_*) represented by |wifi_interface_mode| + * Bitmask does not represent concurrency. + * Examples: + * - If a channel is usable only for STA, then only the WIFI_INTERFACE_STA + * bit would be set for that channel. + * - If 5GHz SAP is not allowed, then none of the 5GHz channels will have + * WIFI_INTERFACE_SOFTAP bit set. + * Note: TDLS bit is set only if there is a STA connection. TDLS bit is set + * on non-STA channels only if TDLS off channel is supported. + */ + u32 iface_mode_mask; +} wifi_usable_channel; + +/* + * wifi_usable_channel_filter + */ +typedef enum { + /* Filter Wifi channels that should be avoided due to cellular coex + * restrictions. Some Wifi channels can have extreme interference + * from/to cellular due to short frequency separation with neighboring + * cellular channels or when there is harmonic and intermodulation + * interference. Channels which only have some performance degradation + * (e.g. power back off is sufficient to deal with coexistence issue) + * can be included and should not be filtered out. + */ + WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE = 1 << 0, + /* Filter channels due to concurrency state. + * Examples: + * - 5GHz SAP operation may be supported in standalone mode, but if + * there is STA connection on 5GHz DFS channel, none of the 5GHz + * channels are usable for SAP if device does not support DFS SAP mode. + * - P2P GO may not be supported on indoor channels in EU during + * standalone mode but if there is a STA connection on indoor channel, + * P2P GO may be supported by some vendors on the same STA channel. + */ + WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY = 1 << 1, + /* This Filter queries Wifi channels and bands that are supported for + * NAN3.1 Instant communication mode. This filter should only be applied to NAN interface. + * If 5G is supported default discovery channel 149/44 is considered, + * If 5G is not supported then channel 6 has to be considered. + * Based on regulatory domain if channel 149 and 44 are restricted, channel 6 should + * be considered for instant communication channel + */ + WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE = 1 << 2, +} wifi_usable_channel_filter; + +typedef enum { + WIFI_SUCCESS = 0, + WIFI_ERROR_NONE = 0, + WIFI_ERROR_UNKNOWN = -1, + WIFI_ERROR_UNINITIALIZED = -2, + WIFI_ERROR_NOT_SUPPORTED = -3, + WIFI_ERROR_NOT_AVAILABLE = -4, // Not available right now, but try later + WIFI_ERROR_INVALID_ARGS = -5, + WIFI_ERROR_INVALID_REQUEST_ID = -6, + WIFI_ERROR_TIMED_OUT = -7, + WIFI_ERROR_TOO_MANY_REQUESTS = -8, // Too many instances of this request + WIFI_ERROR_OUT_OF_MEMORY = -9, + WIFI_ERROR_BUSY = -10, +} wifi_error; + +typedef enum { + WIFI_ACCESS_CATEGORY_BEST_EFFORT = 0, + WIFI_ACCESS_CATEGORY_BACKGROUND = 1, + WIFI_ACCESS_CATEGORY_VIDEO = 2, + WIFI_ACCESS_CATEGORY_VOICE = 3 +} wifi_access_category; + +/* Antenna configuration */ +typedef enum { + WIFI_ANTENNA_UNSPECIFIED = 0, + WIFI_ANTENNA_1X1 = 1, + WIFI_ANTENNA_2X2 = 2, + WIFI_ANTENNA_3X3 = 3, + WIFI_ANTENNA_4X4 = 4, +} wifi_antenna_configuration; + +/* Wifi Radio configuration */ +typedef struct { + /* Operating band */ + wlan_mac_band band; + /* Antenna configuration */ + wifi_antenna_configuration antenna_cfg; +} wifi_radio_configuration; + +/* WiFi Radio Combination */ +typedef struct { + u32 num_radio_configurations; + wifi_radio_configuration radio_configurations[]; +} wifi_radio_combination; + +/* WiFi Radio combinations matrix */ +/* For Example in case of a chip which has two radios, where one radio is + * capable of 2.4GHz 2X2 only and another radio which is capable of either + * 5GHz or 6GHz 2X2, number of possible radio combinations in this case + * are 5 and possible combinations are + * {{{2G 2X2}}, //Standalone 2G + * {{5G 2X2}}, //Standalone 5G + * {{6G 2X2}}, //Standalone 6G + * {{2G 2X2}, {5G 2X2}}, //2G+5G DBS + * {{2G 2X2}, {6G 2X2}}} //2G+6G DBS + * Note: Since this chip doesn’t support 5G+6G simultaneous operation + * as there is only one radio which can support both, So it can only + * do MCC 5G+6G. This table should not get populated with possible MCC + * configurations. This is only for simultaneous radio configurations + * (such as Standalone, multi band simultaneous or single band simultaneous). + */ +typedef struct { + u32 num_radio_combinations; + /* Each row represents possible radio combinations */ + wifi_radio_combination radio_combinations[]; +} wifi_radio_combination_matrix; + +/* Initialize/Cleanup */ + +wifi_error wifi_initialize(wifi_handle* handle); + +/** + * wifi_wait_for_driver + * Function should block until the driver is ready to proceed. + * Any errors from this function is considered fatal & will fail the HAL startup sequence. + * + * on success returns WIFI_SUCCESS + * on failure returns WIFI_ERROR_TIMED_OUT + */ +wifi_error wifi_wait_for_driver_ready(void); + +typedef void (*wifi_cleaned_up_handler)(wifi_handle handle); +void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler); +void wifi_event_loop(wifi_handle handle); + +/* Error handling */ +void wifi_get_error_info(wifi_error err, const char** msg); // return a pointer to a static string + +/* Feature enums */ +#define WIFI_FEATURE_INFRA (uint64_t)0x1 // Basic infrastructure mode +#define WIFI_FEATURE_INFRA_5G (uint64_t)0x2 // Support for 5 GHz Band +#define WIFI_FEATURE_HOTSPOT (uint64_t)0x4 // Support for GAS/ANQP +#define WIFI_FEATURE_P2P (uint64_t)0x8 // Wifi-Direct +#define WIFI_FEATURE_SOFT_AP (uint64_t)0x10 // Soft AP +#define WIFI_FEATURE_GSCAN (uint64_t)0x20 // Google-Scan APIs +#define WIFI_FEATURE_NAN (uint64_t)0x40 // Neighbor Awareness Networking +#define WIFI_FEATURE_D2D_RTT (uint64_t)0x80 // Device-to-device RTT +#define WIFI_FEATURE_D2AP_RTT (uint64_t)0x100 // Device-to-AP RTT +#define WIFI_FEATURE_BATCH_SCAN (uint64_t)0x200 // Batched Scan (legacy) +#define WIFI_FEATURE_PNO (uint64_t)0x400 // Preferred network offload +#define WIFI_FEATURE_ADDITIONAL_STA (uint64_t)0x800 // Support for two STAs +#define WIFI_FEATURE_TDLS (uint64_t)0x1000 // Tunnel directed link setup +#define WIFI_FEATURE_TDLS_OFFCHANNEL (uint64_t)0x2000 // Support for TDLS off channel +#define WIFI_FEATURE_EPR (uint64_t)0x4000 // Enhanced power reporting +#define WIFI_FEATURE_AP_STA (uint64_t)0x8000 // Support for AP STA Concurrency +#define WIFI_FEATURE_LINK_LAYER_STATS (uint64_t)0x10000 // Link layer stats collection +#define WIFI_FEATURE_LOGGER (uint64_t)0x20000 // WiFi Logger +#define WIFI_FEATURE_HAL_EPNO (uint64_t)0x40000 // WiFi PNO enhanced +#define WIFI_FEATURE_RSSI_MONITOR (uint64_t)0x80000 // RSSI Monitor +#define WIFI_FEATURE_MKEEP_ALIVE (uint64_t)0x100000 // WiFi mkeep_alive +#define WIFI_FEATURE_CONFIG_NDO (uint64_t)0x200000 // ND offload configure +#define WIFI_FEATURE_TX_TRANSMIT_POWER (uint64_t)0x400000 // Capture Tx transmit power levels +#define WIFI_FEATURE_CONTROL_ROAMING (uint64_t)0x800000 // Enable/Disable firmware roaming +#define WIFI_FEATURE_IE_WHITELIST (uint64_t)0x1000000 // Support Probe IE white listing +#define WIFI_FEATURE_SCAN_RAND \ + (uint64_t)0x2000000 // Support MAC & Probe Sequence Number randomization +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (uint64_t)0x4000000 // Support Tx Power Limit setting +#define WIFI_FEATURE_USE_BODY_HEAD_SAR \ + (uint64_t)0x8000000 // Support Using Body/Head Proximity for SAR +#define WIFI_FEATURE_DYNAMIC_SET_MAC \ + (uint64_t)0x10000000 // Support changing MAC address without iface reset(down and up) +#define WIFI_FEATURE_SET_LATENCY_MODE (uint64_t)0x40000000 // Support Latency mode setting +#define WIFI_FEATURE_P2P_RAND_MAC (uint64_t)0x80000000 // Support P2P MAC randomization +#define WIFI_FEATURE_INFRA_60G (uint64_t)0x100000000 // Support for 60GHz Band +// Add more features here + +#define IS_MASK_SET(mask, flags) (((flags) & (mask)) == (mask)) + +#define IS_SUPPORTED_FEATURE(feature, featureSet) IS_MASK_SET(feature, featureSet) + +/* Feature set */ +wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set* set); + +/* + * Each row represents a valid feature combination; + * all other combinations are invalid! + */ +wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, + feature_set set[], int* set_size); + +/* multiple interface support */ + +wifi_error wifi_get_ifaces(wifi_handle handle, int* num_ifaces, wifi_interface_handle** ifaces); +wifi_error wifi_get_iface_name(wifi_interface_handle iface, char* name, size_t size); +wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char* name); + +/* STA + STA support - Supported if WIFI_FEATURE_ADDITIONAL_STA is set */ + +/** + * Invoked to indicate that the provided iface is the primary STA iface when there are more + * than 1 STA iface concurrently active. + * + * Note: If the wifi firmware/chip cannot support multiple instances of any offload + * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these + * offloads are at least enabled for the primary interface. If the new primary interface is + * already connected to a network, the firmware must switch all the offloads on + * this new interface without disconnecting. + */ +wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle, wifi_interface_handle iface); + +/** + * When there are 2 or more simultaneous STA connections, this use case hint indicates what + * use-case is being enabled by the framework. This use case hint can be used by the firmware + * to modify various firmware configurations like: + * - Allowed BSSIDs the firmware can choose for the initial connection/roaming attempts. + * - Duty cycle to choose for the 2 STA connections if the radio is in MCC mode. + * - Whether roaming, APF and other offloads needs to be enabled or not. + * + * Note: + * - This will be invoked before an active wifi connection is established on the second interface. + * - This use-case hint is implicitly void when the second STA interface is brought down. + */ +typedef enum { + /** + * Usage: + * - This will be sent down for make before break use-case. + * - Platform is trying to speculatively connect to a second network and evaluate it without + * disrupting the primary connection. + * + * Requirements for Firmware: + * - Do not reduce the number of tx/rx chains of primary connection. + * - If using MCC, should set the MCC duty cycle of the primary connection to be higher than + * the secondary connection (maybe 70/30 split). + * - Should pick the best BSSID for the secondary STA (disregard the chip mode) independent of + * the primary STA: + * - Don’t optimize for DBS vs MCC/SCC + * - Should not impact the primary connection’s bssid selection: + * - Don’t downgrade chains of the existing primary connection. + * - Don’t optimize for DBS vs MCC/SCC. + */ + WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0, + /** + * Usage: + * - This will be sent down for any app requested peer to peer connections. + * - In this case, both the connections needs to be allocated equal resources. + * - For the peer to peer use case, BSSID for the secondary connection will be chosen by the + * framework. + * + * Requirements for Firmware: + * - Can choose MCC or DBS mode depending on the MCC efficiency and HW capability. + * - If using MCC, set the MCC duty cycle of the primary connection to be equal to the secondary + * connection. + * - Prefer BSSID candidates which will help provide the best "overall" performance for both the + * connections. + */ + WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED = 1 +} wifi_multi_sta_use_case; + +wifi_error wifi_multi_sta_set_use_case(wifi_handle handle, wifi_multi_sta_use_case use_case); + +/* Configuration events */ + +typedef struct { + void (*on_country_code_changed)(char code[2]); // We can get this from supplicant too + + // More event handlers +} wifi_event_handler; + +typedef struct { + char iface_name[IFNAMSIZ + 1]; + wifi_channel channel; +} wifi_iface_info; + +typedef struct { + u32 wlan_mac_id; + /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */ + u32 mac_band; + /* Represents the connected Wi-Fi interfaces associated with each MAC */ + int num_iface; + wifi_iface_info* iface_info; +} wifi_mac_info; + +typedef struct { + void (*on_radio_mode_change)(wifi_request_id id, unsigned num_mac, wifi_mac_info* mac_info); +} wifi_radio_mode_change_handler; + +typedef struct { + void (*on_rssi_threshold_breached)(wifi_request_id id, u8* cur_bssid, s8 cur_rssi); +} wifi_rssi_event_handler; + +typedef struct { + void (*on_subsystem_restart)(const char* error); +} wifi_subsystem_restart_handler; + +typedef struct { + void (*on_chre_nan_rtt_change)(chre_nan_rtt_state state); +} wifi_chre_handler; + +wifi_error wifi_set_iface_event_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_event_handler eh); +wifi_error wifi_reset_iface_event_handler(wifi_request_id id, wifi_interface_handle iface); + +wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs); +wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, + wifi_power_scenario scenario); +wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle); +wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode); +wifi_error wifi_map_dscp_access_category(wifi_handle handle, uint32_t start, uint32_t end, + uint32_t access_category); +wifi_error wifi_reset_dscp_mapping(wifi_handle handle); + +wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle, + wifi_subsystem_restart_handler handler); + +/** + * Wifi HAL Thermal Mitigation API + * + * wifi_handle : wifi global handle (note: this is not a interface specific + * command). Mitigation is expected to be applied across all active interfaces + * The implementation and the mitigation action mapping to each mode is chip + * specific. Mitigation will be active until Wifi is turned off or + * WIFI_MITIGATION_NONE mode is sent + * + * mode: Thermal mitigation mode + * WIFI_MITIGATION_NONE : Clear all Wifi thermal mitigation actions + * WIFI_MITIGATION_LIGHT : Light Throttling where UX is not impacted + * WIFI_MITIGATION_MODERATE : Moderate throttling where UX not largely impacted + * WIFI_MITIGATION_SEVERE : Severe throttling where UX is largely impacted + * WIFI_MITIGATION_CRITICAL : Platform has done everything to reduce power + * WIFI_MITIGATION_EMERGENCY: Key components in platform are shutting down + * + * completion_window + * Deadline (in milliseconds) to complete this request, value 0 implies apply + * immediately. Deadline is basically a relaxed limit and allows vendors to + * apply the mitigation within the window (if it cannot apply immediately) + * + * Return + * WIFI_ERROR_NOT_SUPPORTED : Chip does not support thermal mitigation + * WIFI_ERROR_BUSY : Mitigation is supported, but retry later + * WIFI_ERROR_NONE : Mitigation request has been accepted + */ +wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle, wifi_thermal_mode mode, + u32 completion_window); + +typedef struct rx_data_cnt_details_t { + int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ + int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ + int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ +} RX_DATA_WAKE_CNT_DETAILS; + +typedef struct rx_wake_pkt_type_classification_t { + int icmp_pkt; /*wake icmp packet count */ + int icmp6_pkt; /*wake icmp6 packet count */ + int icmp6_ra; /*wake icmp6 RA packet count */ + int icmp6_na; /*wake icmp6 NA packet count */ + int icmp6_ns; /*wake icmp6 NS packet count */ + // ToDo: Any more interesting classification to add? +} RX_WAKE_PKT_TYPE_CLASSFICATION; + +typedef struct rx_multicast_cnt_t { + int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ + int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ + int other_rx_multicast_addr_cnt; /*Rx wake packet was non-ipv4 and non-ipv6*/ +} RX_MULTICAST_WAKE_DATA_CNT; + +/* + * Structure holding all the driver/firmware wake count reasons. + * + * Buffers for the array fields (cmd_event_wake_cnt/driver_fw_local_wake_cnt) + * are allocated and freed by the framework. The size of each allocated + * array is indicated by the corresponding |_cnt| field. HAL needs to fill in + * the corresponding |_used| field to indicate the number of elements used in + * the array. + */ +typedef struct wlan_driver_wake_reason_cnt_t { + int total_cmd_event_wake; /* Total count of cmd event wakes */ + int* cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ + int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ + int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ + + int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ + int* driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ + int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ + int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the + driver */ + + int total_rx_data_wake; /* total data rx packets, that woke up host */ + RX_DATA_WAKE_CNT_DETAILS rx_wake_details; + RX_WAKE_PKT_TYPE_CLASSFICATION rx_wake_pkt_classification_info; + RX_MULTICAST_WAKE_DATA_CNT rx_multicast_wake_pkt_info; +} WLAN_DRIVER_WAKE_REASON_CNT; + +/* Wi-Fi coex channel avoidance support */ + +#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFF + +typedef enum { WIFI_AWARE = 1 << 0, SOFTAP = 1 << 1, WIFI_DIRECT = 1 << 2 } wifi_coex_restriction; + +/** + * Representation of a Wi-Fi channel to be avoided for Wi-Fi coex channel avoidance. + * + * band is represented as an WLAN_MAC* enum value defined in wlan_mac_band. + * If power_cap_dbm is WIFI_COEX_NO_POWER_CAP, then no power cap should be applied if the specified + * channel is used. + */ +typedef struct { + wlan_mac_band band; + u32 channel; + s32 power_cap_dbm; +} wifi_coex_unsafe_channel; + +/* include various feature headers */ + +#include "gscan.h" +#include "link_layer_stats.h" +#include "roam.h" +#include "rtt.h" +#include "tdls.h" +#include "wifi_cached_scan_results.h" +#include "wifi_config.h" +#include "wifi_logger.h" +#include "wifi_nan.h" +#include "wifi_offload.h" +#include "wifi_twt.h" + +// wifi HAL function pointer table +typedef struct { + wifi_error (*wifi_initialize)(wifi_handle*); + wifi_error (*wifi_wait_for_driver_ready)(void); + void (*wifi_cleanup)(wifi_handle, wifi_cleaned_up_handler); + void (*wifi_event_loop)(wifi_handle); + void (*wifi_get_error_info)(wifi_error, const char**); + wifi_error (*wifi_get_supported_feature_set)(wifi_interface_handle, feature_set*); + wifi_error (*wifi_get_concurrency_matrix)(wifi_interface_handle, int, feature_set*, int*); + wifi_error (*wifi_set_scanning_mac_oui)(wifi_interface_handle, unsigned char*); + wifi_error (*wifi_get_supported_channels)(wifi_handle, int*, wifi_channel*); + wifi_error (*wifi_is_epr_supported)(wifi_handle); + wifi_error (*wifi_get_ifaces)(wifi_handle, int*, wifi_interface_handle**); + wifi_error (*wifi_get_iface_name)(wifi_interface_handle, char* name, size_t); + wifi_error (*wifi_set_iface_event_handler)(wifi_request_id, wifi_interface_handle, + wifi_event_handler); + wifi_error (*wifi_reset_iface_event_handler)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_start_gscan)(wifi_request_id, wifi_interface_handle, wifi_scan_cmd_params, + wifi_scan_result_handler); + wifi_error (*wifi_stop_gscan)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_get_cached_gscan_results)(wifi_interface_handle, byte, int, + wifi_cached_scan_results*, int*); + wifi_error (*wifi_set_bssid_hotlist)(wifi_request_id, wifi_interface_handle, + wifi_bssid_hotlist_params, wifi_hotlist_ap_found_handler); + wifi_error (*wifi_reset_bssid_hotlist)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_set_significant_change_handler)(wifi_request_id, wifi_interface_handle, + wifi_significant_change_params, + wifi_significant_change_handler); + wifi_error (*wifi_reset_significant_change_handler)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_get_gscan_capabilities)(wifi_interface_handle, wifi_gscan_capabilities*); + wifi_error (*wifi_set_link_stats)(wifi_interface_handle, wifi_link_layer_params); + wifi_error (*wifi_get_link_stats)(wifi_request_id, wifi_interface_handle, + wifi_stats_result_handler); + wifi_error (*wifi_clear_link_stats)(wifi_interface_handle, u32, u32*, u8, u8*); + wifi_error (*wifi_get_valid_channels)(wifi_interface_handle, int, int, wifi_channel*, int*); + wifi_error (*wifi_rtt_range_request)(wifi_request_id, wifi_interface_handle, unsigned, + wifi_rtt_config[], wifi_rtt_event_handler); + wifi_error (*wifi_rtt_range_cancel)(wifi_request_id, wifi_interface_handle, unsigned, + mac_addr[]); + wifi_error (*wifi_get_rtt_capabilities)(wifi_interface_handle, wifi_rtt_capabilities*); + wifi_error (*wifi_rtt_get_responder_info)(wifi_interface_handle iface, + wifi_rtt_responder* responder_info); + wifi_error (*wifi_enable_responder)(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_info channel_hint, + unsigned max_duration_seconds, + wifi_rtt_responder* responder_info); + wifi_error (*wifi_disable_responder)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_nodfs_flag)(wifi_interface_handle, u32); + wifi_error (*wifi_start_logging)(wifi_interface_handle, u32, u32, u32, u32, char*); + wifi_error (*wifi_set_epno_list)(wifi_request_id, wifi_interface_handle, + const wifi_epno_params*, wifi_epno_handler); + wifi_error (*wifi_reset_epno_list)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_set_country_code)(wifi_interface_handle, const char*); + wifi_error (*wifi_get_firmware_memory_dump)(wifi_interface_handle iface, + wifi_firmware_memory_dump_handler handler); + wifi_error (*wifi_set_log_handler)(wifi_request_id id, wifi_interface_handle iface, + wifi_ring_buffer_data_handler handler); + wifi_error (*wifi_reset_log_handler)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_alert_handler)(wifi_request_id id, wifi_interface_handle iface, + wifi_alert_handler handler); + wifi_error (*wifi_reset_alert_handler)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_get_firmware_version)(wifi_interface_handle iface, char* buffer, + int buffer_size); + wifi_error (*wifi_get_ring_buffers_status)(wifi_interface_handle iface, u32* num_rings, + wifi_ring_buffer_status* status); + wifi_error (*wifi_get_logger_supported_feature_set)(wifi_interface_handle iface, + unsigned int* support); + wifi_error (*wifi_get_ring_data)(wifi_interface_handle iface, char* ring_name); + wifi_error (*wifi_enable_tdls)(wifi_interface_handle, mac_addr, wifi_tdls_params*, + wifi_tdls_handler); + wifi_error (*wifi_disable_tdls)(wifi_interface_handle, mac_addr); + wifi_error (*wifi_get_tdls_status)(wifi_interface_handle, mac_addr, wifi_tdls_status*); + wifi_error (*wifi_get_tdls_capabilities)(wifi_interface_handle iface, + wifi_tdls_capabilities* capabilities); + wifi_error (*wifi_get_driver_version)(wifi_interface_handle iface, char* buffer, + int buffer_size); + wifi_error (*wifi_set_passpoint_list)(wifi_request_id id, wifi_interface_handle iface, int num, + wifi_passpoint_network* networks, + wifi_passpoint_event_handler handler); + wifi_error (*wifi_reset_passpoint_list)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_lci)(wifi_request_id id, wifi_interface_handle iface, + wifi_lci_information* lci); + wifi_error (*wifi_set_lcr)(wifi_request_id id, wifi_interface_handle iface, + wifi_lcr_information* lcr); + wifi_error (*wifi_start_sending_offloaded_packet)(wifi_request_id id, + wifi_interface_handle iface, u16 ether_type, + u8* ip_packet, u16 ip_packet_len, + u8* src_mac_addr, u8* dst_mac_addr, + u32 period_msec); + wifi_error (*wifi_stop_sending_offloaded_packet)(wifi_request_id id, + wifi_interface_handle iface); + wifi_error (*wifi_start_rssi_monitoring)(wifi_request_id id, wifi_interface_handle iface, + s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh); + wifi_error (*wifi_stop_rssi_monitoring)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_get_wake_reason_stats)(wifi_interface_handle iface, + WLAN_DRIVER_WAKE_REASON_CNT* wifi_wake_reason_cnt); + wifi_error (*wifi_configure_nd_offload)(wifi_interface_handle iface, u8 enable); + wifi_error (*wifi_get_driver_memory_dump)(wifi_interface_handle iface, + wifi_driver_memory_dump_callbacks callbacks); + wifi_error (*wifi_start_pkt_fate_monitoring)(wifi_interface_handle iface); + wifi_error (*wifi_get_tx_pkt_fates)(wifi_interface_handle handle, + wifi_tx_report* tx_report_bufs, size_t n_requested_fates, + size_t* n_provided_fates); + wifi_error (*wifi_get_rx_pkt_fates)(wifi_interface_handle handle, + wifi_rx_report* rx_report_bufs, size_t n_requested_fates, + size_t* n_provided_fates); + + /* NAN functions */ + wifi_error (*wifi_nan_enable_request)(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + wifi_error (*wifi_nan_disable_request)(transaction_id id, wifi_interface_handle iface); + wifi_error (*wifi_nan_publish_request)(transaction_id id, wifi_interface_handle iface, + NanPublishRequest* msg); + wifi_error (*wifi_nan_publish_cancel_request)(transaction_id id, wifi_interface_handle iface, + NanPublishCancelRequest* msg); + wifi_error (*wifi_nan_subscribe_request)(transaction_id id, wifi_interface_handle iface, + NanSubscribeRequest* msg); + wifi_error (*wifi_nan_subscribe_cancel_request)(transaction_id id, wifi_interface_handle iface, + NanSubscribeCancelRequest* msg); + wifi_error (*wifi_nan_transmit_followup_request)(transaction_id id, wifi_interface_handle iface, + NanTransmitFollowupRequest* msg); + wifi_error (*wifi_nan_stats_request)(transaction_id id, wifi_interface_handle iface, + NanStatsRequest* msg); + wifi_error (*wifi_nan_config_request)(transaction_id id, wifi_interface_handle iface, + NanConfigRequest* msg); + wifi_error (*wifi_nan_tca_request)(transaction_id id, wifi_interface_handle iface, + NanTCARequest* msg); + wifi_error (*wifi_nan_beacon_sdf_payload_request)(transaction_id id, + wifi_interface_handle iface, + NanBeaconSdfPayloadRequest* msg); + wifi_error (*wifi_nan_register_handler)(wifi_interface_handle iface, + NanCallbackHandler handlers); + wifi_error (*wifi_nan_get_version)(wifi_handle handle, NanVersion* version); + wifi_error (*wifi_nan_get_capabilities)(transaction_id id, wifi_interface_handle iface); + wifi_error (*wifi_nan_data_interface_create)(transaction_id id, wifi_interface_handle iface, + char* iface_name); + wifi_error (*wifi_nan_data_interface_delete)(transaction_id id, wifi_interface_handle iface, + char* iface_name); + wifi_error (*wifi_nan_data_request_initiator)(transaction_id id, wifi_interface_handle iface, + NanDataPathInitiatorRequest* msg); + wifi_error (*wifi_nan_data_indication_response)(transaction_id id, wifi_interface_handle iface, + NanDataPathIndicationResponse* msg); + wifi_error (*wifi_nan_data_end)(transaction_id id, wifi_interface_handle iface, + NanDataPathEndRequest* msg); + wifi_error (*wifi_select_tx_power_scenario)(wifi_interface_handle iface, + wifi_power_scenario scenario); + wifi_error (*wifi_reset_tx_power_scenario)(wifi_interface_handle iface); + + /** + * Returns the chipset's hardware filtering capabilities: + * @param version pointer to version of the packet filter interpreter + * supported, filled in upon return. 0 indicates no support. + * @param max_len pointer to maximum size of the filter bytecode, filled in + * upon return. + */ + wifi_error (*wifi_get_packet_filter_capabilities)(wifi_interface_handle handle, u32* version, + u32* max_len); + /** + * Programs the packet filter. + * @param program pointer to the program byte-code. + * @param len length of the program byte-code. + */ + wifi_error (*wifi_set_packet_filter)(wifi_interface_handle handle, const u8* program, u32 len); + wifi_error (*wifi_read_packet_filter)(wifi_interface_handle handle, u32 src_offset, + u8* host_dst, u32 length); + wifi_error (*wifi_get_roaming_capabilities)(wifi_interface_handle handle, + wifi_roaming_capabilities* caps); + wifi_error (*wifi_enable_firmware_roaming)(wifi_interface_handle handle, + fw_roaming_state_t state); + wifi_error (*wifi_configure_roaming)(wifi_interface_handle handle, + wifi_roaming_config* roaming_config); + wifi_error (*wifi_set_radio_mode_change_handler)(wifi_request_id id, + wifi_interface_handle iface, + wifi_radio_mode_change_handler eh); + wifi_error (*wifi_set_latency_mode)(wifi_interface_handle iface, wifi_latency_mode mode); + wifi_error (*wifi_set_thermal_mitigation_mode)(wifi_handle handle, wifi_thermal_mode mode, + u32 completion_window); + wifi_error (*wifi_map_dscp_access_category)(wifi_handle handle, u32 start, u32 end, + u32 access_category); + wifi_error (*wifi_reset_dscp_mapping)(wifi_handle handle); + + wifi_error (*wifi_virtual_interface_create)(wifi_handle handle, const char* ifname, + wifi_interface_type iface_type); + wifi_error (*wifi_virtual_interface_delete)(wifi_handle handle, const char* ifname); + + wifi_error (*wifi_set_subsystem_restart_handler)(wifi_handle handle, + wifi_subsystem_restart_handler handler); + + /** + * Allow vendor HAL to choose interface name when creating + * an interface. This can be implemented by chips with their + * own interface naming policy. + * If not implemented, the default naming will be used. + */ + wifi_error (*wifi_get_supported_iface_name)(wifi_handle handle, u32 iface_type, char* name, + size_t len); + + /** + * Perform early initialization steps that are needed when WIFI + * is disabled. + * If the function returns failure, it means the vendor HAL is unusable + * (for example, if chip hardware is not installed) and no further + * functions should be called. + */ + wifi_error (*wifi_early_initialize)(void); + + /** + * Get supported feature set which are chip-global, that is + * not dependent on any created interface. + */ + wifi_error (*wifi_get_chip_feature_set)(wifi_handle handle, feature_set* set); + + /** + * Invoked to indicate that the provided iface is the primary STA iface when there are more + * than 1 STA iface concurrently active. + */ + wifi_error (*wifi_multi_sta_set_primary_connection)(wifi_handle handle, + wifi_interface_handle iface); + + /** + * When there are 2 simultaneous STA connections, this use case hint + * indicates what STA + STA use-case is being enabled by the framework. + */ + wifi_error (*wifi_multi_sta_set_use_case)(wifi_handle handle, wifi_multi_sta_use_case use_case); + + /** + * Invoked to indicate that the following list of wifi_coex_unsafe_channel should be avoided + * with the specified restrictions. + * @param unsafeChannels list of current |wifi_coex_unsafe_channel| to avoid. + * @param restrictions bitmask of |wifi_coex_restriction| indicating wifi interfaces to + * restrict from the current unsafe channels. + */ + wifi_error (*wifi_set_coex_unsafe_channels)(wifi_handle handle, u32 num_channels, + wifi_coex_unsafe_channel* unsafeChannels, + u32 restrictions); + + /** + * Invoked to set voip optimization mode for the provided STA iface + */ + wifi_error (*wifi_set_voip_mode)(wifi_interface_handle iface, wifi_voip_mode mode); + + /**@brief twt_register_handler + * Request to register TWT callback before sending any TWT request + * @param wifi_interface_handle: + * @param TwtCallbackHandler: callback function pointers + * @return Synchronous wifi_error + */ + wifi_error (*wifi_twt_register_handler)(wifi_interface_handle iface, + TwtCallbackHandler handler); + + /**@brief twt_get_capability + * Request TWT capability + * @param wifi_interface_handle: + * @return Synchronous wifi_error and TwtCapabilitySet + */ + wifi_error (*wifi_twt_get_capability)(wifi_interface_handle iface, + TwtCapabilitySet* twt_cap_set); + + /**@brief twt_setup_request + * Request to send TWT setup frame + * @param wifi_interface_handle: + * @param TwtSetupRequest: detailed parameters of setup request + * @return Synchronous wifi_error + * @return Asynchronous EventTwtSetupResponse CB return TwtSetupResponse + */ + wifi_error (*wifi_twt_setup_request)(wifi_interface_handle iface, TwtSetupRequest* msg); + + /**@brief twt_teardown_request + * Request to send TWT teardown frame + * @param wifi_interface_handle: + * @param TwtTeardownRequest: detailed parameters of teardown request + * @return Synchronous wifi_error + * @return Asynchronous EventTwtTeardownCompletion CB return TwtTeardownCompletion + * TwtTeardownCompletion may also be received due to other events + * like CSA, BTCX, TWT scheduler, MultiConnection, peer-initiated teardown, etc. + */ + wifi_error (*wifi_twt_teardown_request)(wifi_interface_handle iface, TwtTeardownRequest* msg); + + /**@brief twt_info_frame_request + * Request to send TWT info frame + * @param wifi_interface_handle: + * @param TwtInfoFrameRequest: detailed parameters in info frame + * @return Synchronous wifi_error + * @return Asynchronous EventTwtInfoFrameReceived CB return TwtInfoFrameReceived + * Driver may also receive Peer-initiated TwtInfoFrame + */ + wifi_error (*wifi_twt_info_frame_request)(wifi_interface_handle iface, + TwtInfoFrameRequest* msg); + + /**@brief twt_get_stats + * Request to get TWT stats + * @param wifi_interface_handle: + * @param config_id: configuration ID of TWT request + * @return Synchronous wifi_error and TwtStats + */ + wifi_error (*wifi_twt_get_stats)(wifi_interface_handle iface, u8 config_id, TwtStats* stats); + + /**@brief twt_clear_stats + * Request to clear TWT stats + * @param wifi_interface_handle: + * @param config_id: configuration ID of TWT request + * @return Synchronous wifi_error + */ + wifi_error (*wifi_twt_clear_stats)(wifi_interface_handle iface, u8 config_id); + + /** + * Invoked to set DTIM configuration when the host is in the suspend mode + * @param wifi_interface_handle: + * @param multiplier: when STA in the power saving mode, the wake up interval will be set to + * 1) multiplier * DTIM period if multiplier > 0. + * 2) the device default value if multiplier <=0 + * Some implementations may apply an additional cap to wake up interval in the case of 1). + */ + wifi_error (*wifi_set_dtim_config)(wifi_interface_handle handle, u32 multiplier); + + /**@brief wifi_get_usable_channels + * Request list of usable channels for the requested bands and modes. Usable + * implies channel is allowed as per regulatory for the current country code + * and not restricted due to other hard limitations (e.g. DFS, Coex) In + * certain modes (e.g. STA+SAP) there could be other hard restrictions + * since MCC operation many not be supported by SAP. This API also allows + * driver to return list of usable channels for each mode uniquely to + * distinguish cases where only a limited set of modes are allowed on + * a given channel e.g. srd channels may be supported for P2P but not + * for SAP or P2P-Client may be allowed on an indoor channel but P2P-GO + * may not be allowed. This API is not interface specific and will be + * used to query capabilities of driver in terms of what modes (STA, SAP, + * P2P_CLI, P2P_GO, NAN, TDLS) can be supported on each of the channels. + * @param handle global wifi_handle + * @param band_mask BIT MASK of WLAN_MAC* as represented by |wlan_mac_band| + * @param iface_mode_mask BIT MASK of BIT(WIFI_INTERFACE_*) represented by + * |wifi_interface_mode|. Bitmask respresents all the modes that the + * caller is interested in (e.g. STA, SAP, WFD-CLI, WFD-GO, TDLS, NAN). + * Note: Bitmask does not represent concurrency matrix. If the caller + * is interested in CLI, GO modes, the iface_mode_mask would be set + * to WIFI_INTERFACE_P2P_CLIENT|WIFI_INTERFACE_P2P_GO. + * @param filter_mask BIT MASK of WIFI_USABLE_CHANNEL_FILTER_* represented by + * |wifi_usable_channel_filter|. Indicates if the channel list should + * be filtered based on additional criteria. If filter_mask is not + * specified, driver should return list of usable channels purely + * based on regulatory constraints. + * @param max_size maximum number of |wifi_usable_channel| + * @param size actual number of |wifi_usable_channel| entries returned by driver + * @param channels list of usable channels represented by |wifi_usable_channel| + */ + wifi_error (*wifi_get_usable_channels)(wifi_handle handle, u32 band_mask, u32 iface_mode_mask, + u32 filter_mask, u32 max_size, u32* size, + wifi_usable_channel* channels); + + /** + * Trigger wifi subsystem restart to reload firmware + */ + wifi_error (*wifi_trigger_subsystem_restart)(wifi_handle handle); + + /** + * Invoked to set that the device is operating in an indoor environment. + * @param handle global wifi_handle + * @param isIndoor: true if the device is operating in an indoor + * environment, false otherwise. + * @return Synchronous wifi_error + */ + wifi_error (*wifi_set_indoor_state)(wifi_handle handle, bool isIndoor); + + /**@brief wifi_get_supported_radio_combinations_matrix + * Request all the possible radio combinations this device can offer. + * @param handle global wifi_handle + * @param max_size maximum size allocated for filling the wifi_radio_combination_matrix + * @param wifi_radio_combination_matrix to return all the possible radio + * combinations. + * @param size actual size of wifi_radio_combination_matrix returned from + * lower layer + * + */ + wifi_error (*wifi_get_supported_radio_combinations_matrix)( + wifi_handle handle, u32 max_size, u32* size, + wifi_radio_combination_matrix* radio_combination_matrix); + + /**@brief wifi_nan_rtt_chre_enable_request + * Request to enable CHRE NAN RTT + * @param transaction_id: NAN transaction id + * @param wifi_interface_handle + * @param NanEnableRequest request message + * @return Synchronous wifi_error + */ + wifi_error (*wifi_nan_rtt_chre_enable_request)(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + + /**@brief wifi_nan_rtt_chre_disable_request + * Request to disable CHRE NAN RTT + * @param transaction_id: NAN transaction id + * @param wifi_interface_handle + * @return Synchronous wifi_error + */ + wifi_error (*wifi_nan_rtt_chre_disable_request)(transaction_id id, wifi_interface_handle iface); + + /**@brief wifi_chre_register_handler + * register a handler to get the state of CHR + * @param wifi_interface_handle + * @param wifi_chre_handler: callback function pointer + * @return Synchronous wifi_error + */ + wifi_error (*wifi_chre_register_handler)(wifi_interface_handle iface, + wifi_chre_handler handler); + + /**@brief wifi_enable_tx_power_limits + * Enable WiFi Tx power limis + * @param wifi_interface_handle + * @param isEnable : If enable TX limit or not + * @return Synchronous wifi_error + */ + wifi_error (*wifi_enable_tx_power_limits)(wifi_interface_handle iface, bool isEnable); + + /**@brief wifi_get_cached_scan_results + * Retrieve scan results cached in wifi firmware + * @param wifi_interface_handle + * @param wifi_cached_scan_result_handler : callback function pointer + * @return Synchronous wifi_error + */ + wifi_error (*wifi_get_cached_scan_results)(wifi_interface_handle iface, + wifi_cached_scan_result_handler handler); + /* + * when adding new functions make sure to add stubs in + * hal_tool.cpp::init_wifi_stub_hal_func_table + */ +} wifi_hal_fn; + +wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn* fn); +typedef wifi_error (*init_wifi_vendor_hal_func_table_t)(wifi_hal_fn* fn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h new file mode 100644 index 0000000..76d6f74 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h @@ -0,0 +1,650 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_LOGGER_H +#define __WIFI_HAL_LOGGER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define LOGGER_MAJOR_VERSION 1 +#define LOGGER_MINOR_VERSION 0 +#define LOGGER_MICRO_VERSION 0 + +/** + * WiFi logger life cycle is as follow: + * + * - At initialization time, framework will call wifi_get_ring_buffers_status + * so as to obtain the names and list of supported buffers. + * - When WiFi operation start framework will call wifi_start_logging + * so as to trigger log collection. + * - Developper UI will provide an option to the user, so as it can set the verbose level + * of individual buffer as reported by wifi_get_ring_buffers_status. + * - During wifi operations, driver will periodically report per ring data to framework + * by invoking the on_ring_buffer_data call back. + * - when capturing a bug report, framework will indicate to driver that all the data + * has to be uploaded, urgently, by calling wifi_get_ring_data. + * + * The data uploaded by driver will be stored by framework in separate files, with one stream + * of file per ring. + * Framework will store the files in pcapng format, allowing for easy merging and parsing + * with network analyzer tools. + */ + +typedef int wifi_ring_buffer_id; + +#define PER_PACKET_ENTRY_FLAGS_DIRECTION_TX 1 // 0: TX, 1: RX +#define PER_PACKET_ENTRY_FLAGS_TX_SUCCESS \ + 2 // whether packet was transmitted or + // received/decrypted successfully +#define PER_PACKET_ENTRY_FLAGS_80211_HEADER 4 // has full 802.11 header, else has 802.3 header +#define PER_PACKET_ENTRY_FLAGS_PROTECTED 8 // whether packet was encrypted + +typedef struct { + u8 flags; + u8 tid; // transmit or received tid + u16 MCS; // modulation and bandwidth + u8 rssi; // TX: RSSI of ACK for that packet + // RX: RSSI of packet + u8 num_retries; // number of attempted retries + u16 last_transmit_rate; // last transmit rate in .5 mbps + u16 link_layer_transmit_sequence; // transmit/reeive sequence for that MPDU packet + u64 firmware_entry_timestamp; // TX: firmware timestamp (us) when packet is queued within + // firmware buffer for SDIO/HSIC or into PCIe buffer + // RX: firmware receive timestamp + u64 start_contention_timestamp; // firmware timestamp (us) when packet start contending for the + // medium for the first time, at head of its AC queue, + // or as part of an MPDU or A-MPDU. This timestamp is + // not updated for each retry, only the first transmit attempt. + u64 transmit_success_timestamp; // fimrware timestamp (us) when packet is successfully + // transmitted or aborted because it has exhausted + // its maximum number of retries. + u8 data[0]; // packet data. The length of packet data is determined by the entry_size field of + // the wifi_ring_buffer_entry structure. It is expected that first bytes of the + // packet, or packet headers only (up to TCP or RTP/UDP headers) + // will be copied into the ring +} __attribute__((packed)) wifi_ring_per_packet_status_entry; + +/* Below events refer to the wifi_connectivity_event ring and shall be supported */ +#define WIFI_EVENT_ASSOCIATION_REQUESTED 0 // driver receives association command from kernel +#define WIFI_EVENT_AUTH_COMPLETE 1 +#define WIFI_EVENT_ASSOC_COMPLETE 2 +#define WIFI_EVENT_FW_AUTH_STARTED 3 // fw event indicating auth frames are sent +#define WIFI_EVENT_FW_ASSOC_STARTED 4 // fw event indicating assoc frames are sent +#define WIFI_EVENT_FW_RE_ASSOC_STARTED 5 // fw event indicating reassoc frames are sent +#define WIFI_EVENT_DRIVER_SCAN_REQUESTED 6 +#define WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND 7 +#define WIFI_EVENT_DRIVER_SCAN_COMPLETE 8 +#define WIFI_EVENT_G_SCAN_STARTED 9 +#define WIFI_EVENT_G_SCAN_COMPLETE 10 +#define WIFI_EVENT_DISASSOCIATION_REQUESTED 11 +#define WIFI_EVENT_RE_ASSOCIATION_REQUESTED 12 +#define WIFI_EVENT_ROAM_REQUESTED 13 +#define WIFI_EVENT_BEACON_RECEIVED \ + 14 // received beacon from AP (event enabled + // only in verbose mode) +#define WIFI_EVENT_ROAM_SCAN_STARTED 15 // firmware has triggered a roam scan (not g-scan) +#define WIFI_EVENT_ROAM_SCAN_COMPLETE 16 // firmware has completed a roam scan (not g-scan) +#define WIFI_EVENT_ROAM_SEARCH_STARTED \ + 17 // firmware has started searching for roam + // candidates (with reason =xx) +#define WIFI_EVENT_ROAM_SEARCH_STOPPED \ + 18 // firmware has stopped searching for roam + // candidates (with reason =xx) +#define WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT 20 // received channel switch anouncement from AP +#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START \ + 21 // fw start transmit eapol frame, with + // EAPOL index 1-4 +#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP \ + 22 // fw gives up eapol frame, with rate, + // success/failure and number retries +#define WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED \ + 23 // kernel queue EAPOL for transmission + // in driver with EAPOL index 1-4 +#define WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED \ + 24 // with rate, regardless of the fact that + // EAPOL frame is accepted or rejected by fw +#define WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED \ + 26 // with rate, and eapol index, driver has + // received EAPOL frame and will queue it up + // to wpa_supplicant +#define WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE 27 // with success/failure, parameters +#define WIFI_EVENT_BT_COEX_BT_SCO_START 28 +#define WIFI_EVENT_BT_COEX_BT_SCO_STOP 29 +#define WIFI_EVENT_BT_COEX_BT_SCAN_START \ + 30 // for paging/scan etc., when BT starts transmiting + // twice per BT slot +#define WIFI_EVENT_BT_COEX_BT_SCAN_STOP 31 +#define WIFI_EVENT_BT_COEX_BT_HID_START 32 +#define WIFI_EVENT_BT_COEX_BT_HID_STOP 33 +#define WIFI_EVENT_ROAM_AUTH_STARTED 34 // fw sends auth frame in roaming to next candidate +#define WIFI_EVENT_ROAM_AUTH_COMPLETE 35 // fw receive auth confirm from ap +#define WIFI_EVENT_ROAM_ASSOC_STARTED \ + 36 // firmware sends assoc/reassoc frame in + // roaming to next candidate +#define WIFI_EVENT_ROAM_ASSOC_COMPLETE 37 // firmware receive assoc/reassoc confirm from ap +#define WIFI_EVENT_G_SCAN_STOP 38 // firmware sends stop G_SCAN +#define WIFI_EVENT_G_SCAN_CYCLE_STARTED 39 // firmware indicates G_SCAN scan cycle started +#define WIFI_EVENT_G_SCAN_CYCLE_COMPLETED 40 // firmware indicates G_SCAN scan cycle completed +#define WIFI_EVENT_G_SCAN_BUCKET_STARTED \ + 41 // firmware indicates G_SCAN scan start + // for a particular bucket +#define WIFI_EVENT_G_SCAN_BUCKET_COMPLETED \ + 42 // firmware indicates G_SCAN scan completed for + // for a particular bucket +#define WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE \ + 43 // Event received from firmware about G_SCAN scan + // results being available +#define WIFI_EVENT_G_SCAN_CAPABILITIES \ + 44 // Event received from firmware with G_SCAN + // capabilities +#define WIFI_EVENT_ROAM_CANDIDATE_FOUND \ + 45 // Event received from firmware when eligible + // candidate is found +#define WIFI_EVENT_ROAM_SCAN_CONFIG \ + 46 // Event received from firmware when roam scan + // configuration gets enabled or disabled +#define WIFI_EVENT_AUTH_TIMEOUT 47 // firmware/driver timed out authentication +#define WIFI_EVENT_ASSOC_TIMEOUT 48 // firmware/driver timed out association +#define WIFI_EVENT_MEM_ALLOC_FAILURE 49 // firmware/driver encountered allocation failure +#define WIFI_EVENT_DRIVER_PNO_ADD 50 // driver added a PNO network in firmware +#define WIFI_EVENT_DRIVER_PNO_REMOVE 51 // driver removed a PNO network in firmware +#define WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND \ + 52 // driver received PNO networks + // found indication from firmware +#define WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED 53 // driver triggered a scan for PNO networks +#define WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND \ + 54 // driver received scan results + // of PNO networks +#define WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE \ + 55 // driver updated scan results from + // PNO networks to cfg80211 + +/** + * Parameters of wifi logger events are TLVs + * Event parameters tags are defined as: + */ +#define WIFI_TAG_VENDOR_SPECIFIC 0 // take a byte stream as parameter +#define WIFI_TAG_BSSID 1 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR 2 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_SSID 3 // takes a 32 bytes SSID address as parameter +#define WIFI_TAG_STATUS 4 // takes an integer as parameter +#define WIFI_TAG_CHANNEL_SPEC 5 // takes one or more wifi_channel_spec as parameter +#define WIFI_TAG_WAKE_LOCK_EVENT 6 // takes a wake_lock_event struct as parameter +#define WIFI_TAG_ADDR1 7 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR2 8 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR3 9 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR4 10 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_TSF 11 // take a 64 bits TSF value as parameter +#define WIFI_TAG_IE \ + 12 // take one or more specific 802.11 IEs parameter, + // IEs are in turn indicated in TLV format as per + // 802.11 spec +#define WIFI_TAG_INTERFACE 13 // take interface name as parameter +#define WIFI_TAG_REASON_CODE 14 // take a reason code as per 802.11 as parameter +#define WIFI_TAG_RATE_MBPS 15 // take a wifi rate in 0.5 mbps +#define WIFI_TAG_REQUEST_ID 16 // take an integer as parameter +#define WIFI_TAG_BUCKET_ID 17 // take an integer as parameter +#define WIFI_TAG_GSCAN_PARAMS 18 // takes a wifi_scan_cmd_params struct as parameter +#define WIFI_TAG_GSCAN_CAPABILITIES 19 // takes a wifi_gscan_capabilities struct as parameter +#define WIFI_TAG_SCAN_ID 20 // take an integer as parameter +#define WIFI_TAG_RSSI 21 // take an integer as parameter +#define WIFI_TAG_CHANNEL 22 // take an integer as parameter +#define WIFI_TAG_LINK_ID 23 // take an integer as parameter +#define WIFI_TAG_LINK_ROLE 24 // take an integer as parameter +#define WIFI_TAG_LINK_STATE 25 // take an integer as parameter +#define WIFI_TAG_LINK_TYPE 26 // take an integer as parameter +#define WIFI_TAG_TSCO 27 // take an integer as parameter +#define WIFI_TAG_RSCO 28 // take an integer as parameter +#define WIFI_TAG_EAPOL_MESSAGE_TYPE \ + 29 // take an integer as parameter + // M1-1, M2-2, M3-3, M4-4 + +typedef struct { + u16 tag; + u16 length; // length of value + u8 value[0]; +} __attribute__((packed)) tlv_log; + +typedef struct { + u16 event; + tlv_log tlvs[0]; // separate parameter structure per event to be provided and optional data + // the event_data is expected to include an official android part, with some + // parameter as transmit rate, num retries, num scan result found etc... + // as well, event_data can include a vendor proprietary part which is + // understood by the developer only. +} __attribute__((packed)) wifi_ring_buffer_driver_connectivity_event; + +/** + * Ring buffer name for power events ring. note that power event are extremely frequents + * and thus should be stored in their own ring/file so as not to clobber connectivity events. + */ +typedef struct { + int status; // 0 taken, 1 released + int reason; // reason why this wake lock is taken + char name[0]; // null terminated +} __attribute__((packed)) wake_lock_event; + +typedef struct { + u16 event; + tlv_log tlvs[0]; +} __attribute__((packed)) wifi_power_event; + +/** + * This structure represent a logger entry within a ring buffer. + * Wifi driver are responsible to manage the ring buffer and write the debug + * information into those rings. + * + * In general, the debug entries can be used to store meaningful 802.11 information (SME, MLME, + * connection and packet statistics) as well as vendor proprietary data that is specific to a + * specific driver or chipset. + * Binary entries can be used so as to store packet data or vendor specific information and + * will be treated as blobs of data by android. + * + * A user land process will be started by framework so as to periodically retrieve the + * data logged by drivers into their ring buffer, store the data into log files and include + * the logs into android bugreports. + */ +enum { + RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)), // set for binary entries + RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1)) // set if 64 bits timestamp is present +}; + +enum { + ENTRY_TYPE_CONNECT_EVENT = 1, + ENTRY_TYPE_PKT, + ENTRY_TYPE_WAKE_LOCK, + ENTRY_TYPE_POWER_EVENT, + ENTRY_TYPE_DATA +}; + +typedef struct { + u16 entry_size; // the size of payload excluding the header. + u8 flags; + u8 type; // entry type + u64 timestamp; // present if has_timestamp bit is set. +} __attribute__((packed)) wifi_ring_buffer_entry; + +#define WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES 0x00000001 // set if binary entries are present +#define WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES 0x00000002 // set if ascii entries are present + +/* ring buffer params */ +/** + * written_bytes and read_bytes implement a producer consumer API + * hence written_bytes >= read_bytes + * a modulo arithmetic of the buffer size has to be applied to those counters: + * actual offset into ring buffer = written_bytes % ring_buffer_byte_size + * + */ +typedef struct { + u8 name[32]; + u32 flags; + wifi_ring_buffer_id ring_id; // unique integer representing the ring + u32 ring_buffer_byte_size; // total memory size allocated for the buffer + u32 verbose_level; // verbose level for ring buffer + u32 written_bytes; // number of bytes that was written to the buffer by driver, + // monotonously increasing integer + u32 read_bytes; // number of bytes that was read from the buffer by user land, + // monotonously increasing integer + u32 written_records; // number of records that was written to the buffer by driver, + // monotonously increasing integer +} wifi_ring_buffer_status; + +/** + * Callback for reporting ring data + * + * The ring buffer data collection is event based: + * - Driver calls on_ring_buffer_data when new records are available, the wifi_ring_buffer_status + * passed up to framework in the call back indicates to framework if more data is available in + * the ring buffer. It is not expected that driver will necessarily always empty the ring + * immediately as data is available, instead driver will report data every X seconds or if + * N bytes are available. + * - In the case where a bug report has to be captured, framework will require driver to upload + * all data immediately. This is indicated to driver when framework calls wifi_get_ringdata. + * When framework calls wifi_get_ring_data, driver will start sending all available data in the + * indicated ring by repeatedly invoking the on_ring_buffer_data callback. + * + * The callback is called by log handler whenever ring data comes in driver. + */ +typedef struct { + void (*on_ring_buffer_data)(char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status); +} wifi_ring_buffer_data_handler; + +/** + * API to set the log handler for getting ring data + * - Only a single instance of log handler can be instantiated for each ring buffer. + */ +wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_ring_buffer_data_handler handler); + +/* API to reset the log handler */ +wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface); + +/** + * Callback for reporting FW dump + * + * The buffer data collection is event based such as FW health check or FW dump. + * The callback is called by alert handler. + */ +typedef struct { + void (*on_alert)(wifi_request_id id, char* buffer, int buffer_size, int err_code); +} wifi_alert_handler; + +/* + * API to set the alert handler for the alert case in Wi-Fi Chip + * - Only a single instance of alert handler can be instantiated. + */ +wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_alert_handler handler); + +/* API to reset the alert handler */ +wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface); + +/* API for framework to indicate driver has to upload and drain all data of a given ring */ +wifi_error wifi_get_ring_data(wifi_interface_handle iface, char* ring_name); + +/** + * API to trigger the debug collection. + * Unless his API is invoked - logging is not triggered. + * - Verbose_level 0 corresponds to no collection, + * and it makes log handler stop by no more events from driver. + * - Verbose_level 1 correspond to normal log level, with minimal user impact. + * This is the default value. + * - Verbose_level 2 are enabled when user is lazily trying to reproduce a problem, + * wifi performances and power can be impacted but device should not otherwise be + * significantly impacted. + * - Verbose_level 3+ are used when trying to actively debug a problem. + * + * ring_name represent the name of the ring for which data collection shall start. + * + * flags: TBD parameter used to enable/disable specific events on a ring + * max_interval: maximum interval in seconds for driver to invoke on_ring_buffer_data, + * ignore if zero + * min_data_size: minimum data size in buffer for driver to invoke on_ring_buffer_data, + * ignore if zero + */ +wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level, u32 flags, + u32 max_interval_sec, u32 min_data_size, char* ring_name); + +/** + * API to get the status of all ring buffers supported by driver. + * - Caller is responsible to allocate / free ring buffer status. + * - Maximum no of ring buffer would be 10. + */ +wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface, u32* num_rings, + wifi_ring_buffer_status* status); + +/** + * Synchronous memory dump by user request. + * - Caller is responsible to store memory dump data into a local, + * e.g., /data/misc/wifi/memdump.bin + */ +typedef struct { + void (*on_firmware_memory_dump)(char* buffer, int buffer_size); +} wifi_firmware_memory_dump_handler; + +/** + * API to collect a firmware memory dump for a given iface by async memdump event. + * - Triggered by Alerthandler, esp. when FW problem or FW health check happens + * - Caller is responsible to store fw dump data into a local, + * e.g., /data/misc/wifi/alertdump-1.bin + */ +wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface, + wifi_firmware_memory_dump_handler handler); + +/** + * API to collect a firmware version string. + * - Caller is responsible to allocate / free a buffer to retrieve firmware verion info. + * - Max string will be at most 256 bytes. + */ +wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char* buffer, int buffer_size); + +/** + * API to collect a driver version string. + * - Caller is responsible to allocate / free a buffer to retrieve driver verion info. + * - Max string will be at most 256 bytes. + */ +wifi_error wifi_get_driver_version(wifi_interface_handle iface, char* buffer, int buffer_size); + +/* Feature set */ +enum { + WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW + WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status + WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event + WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver + WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver + WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW + WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW + WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state + WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate +}; + +/** + * API to retrieve the current supportive features. + * - An integer variable is enough to have bit mapping info by caller. + */ +wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface, + unsigned int* support); + +typedef struct { + /* Buffer is to be allocated and freed by HAL implementation. */ + void (*on_driver_memory_dump)(char* buffer, int buffer_size); +} wifi_driver_memory_dump_callbacks; + +/** + API to collect driver state. + + Framework will call this API soon before or after (but not + concurrently with) wifi_get_firmware_memory_dump(). Capturing + firmware and driver dumps is intended to help identify + inconsistent state between these components. + + - In response to this call, HAL implementation should make one or + more calls to callbacks.on_driver_memory_dump(). Framework will + copy data out of the received |buffer|s, and concatenate the + contents thereof. + - HAL implemention will indicate completion of the driver memory + dump by returning from this call. +*/ +wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface, + wifi_driver_memory_dump_callbacks callbacks); + +/* packet fate logs */ + +#define MD5_PREFIX_LEN 4 +#define MAX_FATE_LOG_LEN 32 +#define MAX_FRAME_LEN_ETHERNET 1518 +#define MAX_FRAME_LEN_80211_MGMT 2352 // 802.11-2012 Fig. 8-34 + +typedef enum { + // Sent over air and ACKed. + TX_PKT_FATE_ACKED, + + // Sent over air but not ACKed. (Normal for broadcast/multicast.) + TX_PKT_FATE_SENT, + + // Queued within firmware, but not yet sent over air. + TX_PKT_FATE_FW_QUEUED, + + // Dropped by firmware as invalid. E.g. bad source address, bad checksum, + // or invalid for current state. + TX_PKT_FATE_FW_DROP_INVALID, + + // Dropped by firmware due to lack of buffer space. + TX_PKT_FATE_FW_DROP_NOBUFS, + + // Dropped by firmware for any other reason. Includes frames that + // were sent by driver to firmware, but unaccounted for by + // firmware. + TX_PKT_FATE_FW_DROP_OTHER, + + // Queued within driver, not yet sent to firmware. + TX_PKT_FATE_DRV_QUEUED, + + // Dropped by driver as invalid. E.g. bad source address, or + // invalid for current state. + TX_PKT_FATE_DRV_DROP_INVALID, + + // Dropped by driver due to lack of buffer space. + TX_PKT_FATE_DRV_DROP_NOBUFS, + + // Dropped by driver for any other reason. + TX_PKT_FATE_DRV_DROP_OTHER, +} wifi_tx_packet_fate; + +typedef enum { + // Valid and delivered to network stack (e.g., netif_rx()). + RX_PKT_FATE_SUCCESS, + + // Queued within firmware, but not yet sent to driver. + RX_PKT_FATE_FW_QUEUED, + + // Dropped by firmware due to host-programmable filters. + RX_PKT_FATE_FW_DROP_FILTER, + + // Dropped by firmware as invalid. E.g. bad checksum, decrypt failed, + // or invalid for current state. + RX_PKT_FATE_FW_DROP_INVALID, + + // Dropped by firmware due to lack of buffer space. + RX_PKT_FATE_FW_DROP_NOBUFS, + + // Dropped by firmware for any other reason. + RX_PKT_FATE_FW_DROP_OTHER, + + // Queued within driver, not yet delivered to network stack. + RX_PKT_FATE_DRV_QUEUED, + + // Dropped by driver due to filter rules. + RX_PKT_FATE_DRV_DROP_FILTER, + + // Dropped by driver as invalid. E.g. not permitted in current state. + RX_PKT_FATE_DRV_DROP_INVALID, + + // Dropped by driver due to lack of buffer space. + RX_PKT_FATE_DRV_DROP_NOBUFS, + + // Dropped by driver for any other reason. + RX_PKT_FATE_DRV_DROP_OTHER, +} wifi_rx_packet_fate; + +typedef enum { + FRAME_TYPE_UNKNOWN, + FRAME_TYPE_ETHERNET_II, + FRAME_TYPE_80211_MGMT, +} frame_type; + +typedef struct { + // The type of MAC-layer frame that this frame_info holds. + // - For data frames, use FRAME_TYPE_ETHERNET_II. + // - For management frames, use FRAME_TYPE_80211_MGMT. + // - If the type of the frame is unknown, use FRAME_TYPE_UNKNOWN. + frame_type payload_type; + + // The number of bytes included in |frame_content|. If the frame + // contents are missing (e.g. RX frame dropped in firmware), + // |frame_len| should be set to 0. + size_t frame_len; + + // Host clock when this frame was received by the driver (either + // outbound from the host network stack, or inbound from the + // firmware). + // - The timestamp should be taken from a clock which includes time + // the host spent suspended (e.g. ktime_get_boottime()). + // - If no host timestamp is available (e.g. RX frame was dropped in + // firmware), this field should be set to 0. + u32 driver_timestamp_usec; + + // Firmware clock when this frame was received by the firmware + // (either outbound from the host, or inbound from a remote + // station). + // - The timestamp should be taken from a clock which includes time + // firmware spent suspended (if applicable). + // - If no firmware timestamp is available (e.g. TX frame was + // dropped by driver), this field should be set to 0. + // - Consumers of |frame_info| should _not_ assume any + // synchronization between driver and firmware clocks. + u32 firmware_timestamp_usec; + + // Actual frame content. + // - Should be provided for TX frames originated by the host. + // - Should be provided for RX frames received by the driver. + // - Optionally provided for TX frames originated by firmware. (At + // discretion of HAL implementation.) + // - Optionally provided for RX frames dropped in firmware. (At + // discretion of HAL implementation.) + // - If frame content is not provided, |frame_len| should be set + // to 0. + union { + char ethernet_ii_bytes[MAX_FRAME_LEN_ETHERNET]; + char ieee_80211_mgmt_bytes[MAX_FRAME_LEN_80211_MGMT]; + } frame_content; +} frame_info; + +typedef struct { + // Prefix of MD5 hash of |frame_inf.frame_content|. If frame + // content is not provided, prefix of MD5 hash over the same data + // that would be in frame_content, if frame content were provided. + char md5_prefix[MD5_PREFIX_LEN]; + wifi_tx_packet_fate fate; + frame_info frame_inf; +} wifi_tx_report; + +typedef struct { + // Prefix of MD5 hash of |frame_inf.frame_content|. If frame + // content is not provided, prefix of MD5 hash over the same data + // that would be in frame_content, if frame content were provided. + char md5_prefix[MD5_PREFIX_LEN]; + wifi_rx_packet_fate fate; + frame_info frame_inf; +} wifi_rx_report; + +/** + API to start packet fate monitoring. + - Once stared, monitoring should remain active until HAL is unloaded. + - When HAL is unloaded, all packet fate buffers should be cleared. +*/ +wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle); + +/** + API to retrieve fates of outbound packets. + - HAL implementation should fill |tx_report_bufs| with fates of + _first_ min(n_requested_fates, actual packets) frames + transmitted for the most recent association. The fate reports + should follow the same order as their respective packets. + - HAL implementation may choose (but is not required) to include + reports for management frames. + - Packets reported by firmware, but not recognized by driver, + should be included. However, the ordering of the corresponding + reports is at the discretion of HAL implementation. + - Framework may call this API multiple times for the same association. + - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. + - Framework will allocate and free the referenced storage. +*/ +wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle, wifi_tx_report* tx_report_bufs, + size_t n_requested_fates, size_t* n_provided_fates); + +/** + API to retrieve fates of inbound packets. + - HAL implementation should fill |rx_report_bufs| with fates of + _first_ min(n_requested_fates, actual packets) frames + received for the most recent association. The fate reports + should follow the same order as their respective packets. + - HAL implementation may choose (but is not required) to include + reports for management frames. + - Packets reported by firmware, but not recognized by driver, + should be included. However, the ordering of the corresponding + reports is at the discretion of HAL implementation. + - Framework may call this API multiple times for the same association. + - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. + - Framework will allocate and free the referenced storage. +*/ +wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle, wifi_rx_report* rx_report_bufs, + size_t n_requested_fates, size_t* n_provided_fates); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_STATS_ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h new file mode 100644 index 0000000..3591b98 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h @@ -0,0 +1,2726 @@ +/* + * 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 __NAN_H__ +#define __NAN_H__ + +#include <net/if.h> +#include <stdbool.h> +#include "wifi_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************************************************************** + * Neighbour Aware Network Service Structures and Functions + *****************************************************************************/ + +/* + Definitions + All multi-byte fields within all NAN protocol stack messages are assumed to be in Little Endian + order. +*/ + +typedef int NanVersion; +typedef u16 transaction_id; +typedef u32 NanDataPathId; + +#define NAN_MAC_ADDR_LEN 6 +#define NAN_MAJOR_VERSION 2 +#define NAN_MINOR_VERSION 0 +#define NAN_MICRO_VERSION 1 +#define NAN_MAX_SOCIAL_CHANNELS 3 + +/* NAN Maximum Lengths */ +#define NAN_MAX_SERVICE_NAME_LEN 255 +#define NAN_MAX_MATCH_FILTER_LEN 255 +#define NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024 +#define NAN_MAX_VSA_DATA_LEN 1024 +#define NAN_MAX_MESH_DATA_LEN 32 +#define NAN_MAX_INFRA_DATA_LEN 32 +#define NAN_MAX_CLUSTER_ATTRIBUTE_LEN 255 +#define NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42 +#define NAN_MAX_FAM_CHANNELS 32 +#define NAN_MAX_POSTDISCOVERY_LEN 5 +#define NAN_MAX_FRAME_DATA_LEN 504 +#define NAN_DP_MAX_APP_INFO_LEN 512 +#define NAN_ERROR_STR_LEN 255 +#define NAN_PMK_INFO_LEN 32 +#define NAN_MAX_SCID_BUF_LEN 1024 +#define NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN 1024 +#define NAN_SECURITY_MIN_PASSPHRASE_LEN 8 +#define NAN_SECURITY_MAX_PASSPHRASE_LEN 63 +#define NAN_MAX_CHANNEL_INFO_SUPPORTED 4 + +/* + Definition of various NanResponseType +*/ +typedef enum { + NAN_RESPONSE_ENABLED = 0, + NAN_RESPONSE_DISABLED = 1, + NAN_RESPONSE_PUBLISH = 2, + NAN_RESPONSE_PUBLISH_CANCEL = 3, + NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4, + NAN_RESPONSE_SUBSCRIBE = 5, + NAN_RESPONSE_SUBSCRIBE_CANCEL = 6, + NAN_RESPONSE_STATS = 7, + NAN_RESPONSE_CONFIG = 8, + NAN_RESPONSE_TCA = 9, + NAN_RESPONSE_ERROR = 10, + NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, + NAN_GET_CAPABILITIES = 12, + NAN_DP_INTERFACE_CREATE = 13, + NAN_DP_INTERFACE_DELETE = 14, + NAN_DP_INITIATOR_RESPONSE = 15, + NAN_DP_RESPONDER_RESPONSE = 16, + NAN_DP_END = 17 +} NanResponseType; + +/* NAN Publish Types */ +typedef enum { + NAN_PUBLISH_TYPE_UNSOLICITED = 0, + NAN_PUBLISH_TYPE_SOLICITED, + NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED +} NanPublishType; + +/* NAN Transmit Priorities */ +typedef enum { NAN_TX_PRIORITY_NORMAL = 0, NAN_TX_PRIORITY_HIGH } NanTxPriority; + +/* NAN Statistics Request ID Codes */ +typedef enum { + NAN_STATS_ID_DE_PUBLISH = 0, + NAN_STATS_ID_DE_SUBSCRIBE, + NAN_STATS_ID_DE_MAC, + NAN_STATS_ID_DE_TIMING_SYNC, + NAN_STATS_ID_DE_DW, + NAN_STATS_ID_DE +} NanStatsType; + +/* NAN Protocol Event ID Codes */ +typedef enum { + NAN_EVENT_ID_DISC_MAC_ADDR = 0, + NAN_EVENT_ID_STARTED_CLUSTER, + NAN_EVENT_ID_JOINED_CLUSTER +} NanDiscEngEventType; + +/* NAN Data Path type */ +typedef enum { NAN_DATA_PATH_UNICAST_MSG = 0, NAN_DATA_PATH_MULTICAST_MSG } NdpType; + +/* NAN Ranging Configuration */ +typedef enum { NAN_RANGING_DISABLE = 0, NAN_RANGING_ENABLE } NanRangingState; + +/* TCA Type */ +typedef enum { NAN_TCA_ID_CLUSTER_SIZE = 0 } NanTcaType; + +/* NAN Channel Info */ +typedef struct { + u32 channel; + u32 bandwidth; + u32 nss; +} NanChannelInfo; + +/* + Various NAN Protocol Response code +*/ +typedef enum { + /* NAN Protocol Response Codes */ + NAN_STATUS_SUCCESS = 0, + /* NAN Discovery Engine/Host driver failures */ + NAN_STATUS_INTERNAL_FAILURE = 1, + /* NAN OTA failures */ + NAN_STATUS_PROTOCOL_FAILURE = 2, + /* if the publish/subscribe id is invalid */ + NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3, + /* If we run out of resources allocated */ + NAN_STATUS_NO_RESOURCE_AVAILABLE = 4, + /* if invalid params are passed */ + NAN_STATUS_INVALID_PARAM = 5, + /* if the requestor instance id is invalid */ + NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6, + /* if the ndp id is invalid */ + NAN_STATUS_INVALID_NDP_ID = 7, + /* if NAN is enabled when wifi is turned off */ + NAN_STATUS_NAN_NOT_ALLOWED = 8, + /* if over the air ack is not received */ + NAN_STATUS_NO_OTA_ACK = 9, + /* If NAN is already enabled and we are try to re-enable the same */ + NAN_STATUS_ALREADY_ENABLED = 10, + /* If followup message internal queue is full */ + NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11, + /* Unsupported concurrency session enabled, NAN disabled notified */ + NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12 +} NanStatusType; + +/* NAN Transmit Types */ +typedef enum { NAN_TX_TYPE_BROADCAST = 0, NAN_TX_TYPE_UNICAST } NanTxType; + +/* NAN Subscribe Type */ +typedef enum { NAN_SUBSCRIBE_TYPE_PASSIVE = 0, NAN_SUBSCRIBE_TYPE_ACTIVE } NanSubscribeType; + +/* NAN Service Response Filter Attribute Bit */ +typedef enum { NAN_SRF_ATTR_BLOOM_FILTER = 0, NAN_SRF_ATTR_PARTIAL_MAC_ADDR } NanSRFType; + +/* NAN Service Response Filter Include Bit */ +typedef enum { NAN_SRF_INCLUDE_DO_NOT_RESPOND = 0, NAN_SRF_INCLUDE_RESPOND } NanSRFIncludeType; + +/* NAN Match indication type */ +typedef enum { + NAN_MATCH_ALG_MATCH_ONCE = 0, + NAN_MATCH_ALG_MATCH_CONTINUOUS, + NAN_MATCH_ALG_MATCH_NEVER +} NanMatchAlg; + +/* NAN Transmit Window Type */ +typedef enum { NAN_TRANSMIT_IN_DW = 0, NAN_TRANSMIT_IN_FAW } NanTransmitWindowType; + +/* NAN SRF State in Subscribe */ +typedef enum { NAN_DO_NOT_USE_SRF = 0, NAN_USE_SRF } NanSRFState; + +/* NAN Include SSI in MatchInd */ +typedef enum { + NAN_SSI_NOT_REQUIRED_IN_MATCH_IND = 0, + NAN_SSI_REQUIRED_IN_MATCH_IND +} NanSsiInMatchInd; + +/* NAN DP security Configuration */ +typedef enum { NAN_DP_CONFIG_NO_SECURITY = 0, NAN_DP_CONFIG_SECURITY } NanDataPathSecurityCfgStatus; + +typedef enum { NAN_QOS_NOT_REQUIRED = 0, NAN_QOS_REQUIRED } NanQosCfgStatus; + +/* Data request Responder's response */ +typedef enum { NAN_DP_REQUEST_ACCEPT = 0, NAN_DP_REQUEST_REJECT } NanDataPathResponseCode; + +/* NAN DP channel config options */ +typedef enum { + NAN_DP_CHANNEL_NOT_REQUESTED = 0, + NAN_DP_REQUEST_CHANNEL_SETUP, + NAN_DP_FORCE_CHANNEL_SETUP +} NanDataPathChannelCfg; + +/* Enable/Disable NAN Ranging Auto response */ +typedef enum { + NAN_RANGING_AUTO_RESPONSE_ENABLE = 1, + NAN_RANGING_AUTO_RESPONSE_DISABLE +} NanRangingAutoResponse; + +/* Enable/Disable NAN service range report */ +typedef enum { NAN_DISABLE_RANGE_REPORT = 1, NAN_ENABLE_RANGE_REPORT } NanRangeReport; + +/* NAN Range Response */ +typedef enum { + NAN_RANGE_REQUEST_ACCEPT = 1, + NAN_RANGE_REQUEST_REJECT, + NAN_RANGE_REQUEST_CANCEL +} NanRangeResponse; + +/* NAN Security Key Input Type*/ +typedef enum { + NAN_SECURITY_KEY_INPUT_PMK = 1, + NAN_SECURITY_KEY_INPUT_PASSPHRASE +} NanSecurityKeyInputType; + +typedef struct { + /* pmk length */ + u32 pmk_len; + /* + PMK: Info is optional in Discovery phase. + PMK info can be passed during + the NDP session. + */ + u8 pmk[NAN_PMK_INFO_LEN]; +} NanSecurityPmk; + +typedef struct { + /* passphrase length */ + u32 passphrase_len; + /* + passphrase info is optional in Discovery phase. + passphrase info can be passed during + the NDP session. + */ + u8 passphrase[NAN_SECURITY_MAX_PASSPHRASE_LEN]; +} NanSecurityPassPhrase; + +typedef struct { + NanSecurityKeyInputType key_type; + union { + NanSecurityPmk pmk_info; + NanSecurityPassPhrase passphrase_info; + } body; +} NanSecurityKeyInfo; + +/* NAN Security Cipher Suites Mask */ +#define NAN_CIPHER_SUITE_SHARED_KEY_NONE 0x00 +#define NAN_CIPHER_SUITE_SHARED_KEY_128_MASK 0x01 +#define NAN_CIPHER_SUITE_SHARED_KEY_256_MASK 0x02 +#define NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK 0x04 +#define NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK 0x08 + +/* NAN ranging indication condition MASKS */ +#define NAN_RANGING_INDICATE_CONTINUOUS_MASK 0x01 +#define NAN_RANGING_INDICATE_INGRESS_MET_MASK 0x02 +#define NAN_RANGING_INDICATE_EGRESS_MET_MASK 0x04 + +/* NAN schedule update reason MASKS */ +#define NAN_SCHEDULE_UPDATE_NSS_MASK 0x01 +#define NAN_SCHEDULE_UPDATE_CHANNEL_MASK 0x02 + +/* + Structure to set the Service Descriptor Extension + Attribute (SDEA) passed as part of NanPublishRequest/ + NanSubscribeRequest/NanMatchInd. +*/ +typedef struct { + /* + Optional configuration of Data Path Enable request. + configure flag determines whether configuration needs + to be passed or not. + */ + u8 config_nan_data_path; + NdpType ndp_type; + /* + NAN secuirty required flag to indicate + if the security is enabled or disabled + */ + NanDataPathSecurityCfgStatus security_cfg; + /* + NAN ranging required flag to indicate + if ranging is enabled on disabled + */ + NanRangingState ranging_state; + /* + Enable/Disable Ranging report, + when configured NanRangeReportInd received + */ + NanRangeReport range_report; + /* + NAN QOS required flag to indicate + if QOS is required or not. + */ + NanQosCfgStatus qos_cfg; +} NanSdeaCtrlParams; + +/* + Nan Ranging Peer Info in MatchInd +*/ +typedef struct { + /* + Distance to the NAN device with the MAC address indicated + with ranged mac address. + */ + u32 range_measurement_mm; + /* Ranging event matching the configuration of continuous/ingress/egress. */ + u32 ranging_event_type; +} NanRangeInfo; + +/* Nan/NDP Capabilites info */ +typedef struct { + u32 max_concurrent_nan_clusters; + u32 max_publishes; + u32 max_subscribes; + u32 max_service_name_len; + u32 max_match_filter_len; + u32 max_total_match_filter_len; + u32 max_service_specific_info_len; + u32 max_vsa_data_len; + u32 max_mesh_data_len; + u32 max_ndi_interfaces; + u32 max_ndp_sessions; + u32 max_app_info_len; + u32 max_queued_transmit_followup_msgs; + u32 ndp_supported_bands; + u32 cipher_suites_supported; + u32 max_scid_len; + bool is_ndp_security_supported; + u32 max_sdea_service_specific_info_len; + u32 max_subscribe_address; + u32 ndpe_attr_supported; + bool is_instant_mode_supported; +} NanCapabilities; + +/* + Nan accept policy: Per service basis policy + Based on this policy(ALL/NONE), responder side + will send ACCEPT/REJECT +*/ +typedef enum { + NAN_SERVICE_ACCEPT_POLICY_NONE = 0, + /* Default value */ + NAN_SERVICE_ACCEPT_POLICY_ALL +} NanServiceAcceptPolicy; + +/* + Host can send Vendor specific attributes which the Discovery Engine can + enclose in Beacons and/or Service Discovery frames transmitted. + Below structure is used to populate that. +*/ +typedef struct { + /* + 0 = transmit only in the next discovery window + 1 = transmit in next 16 discovery window + */ + u8 payload_transmit_flag; + /* + Below flags will determine in which all frames + the vendor specific attributes should be included + */ + u8 tx_in_discovery_beacon; + u8 tx_in_sync_beacon; + u8 tx_in_service_discovery; + /* Organizationally Unique Identifier */ + u32 vendor_oui; + /* + vendor specific attribute to be transmitted + vsa_len : Length of the vsa data. + */ + u32 vsa_len; + u8 vsa[NAN_MAX_VSA_DATA_LEN]; +} NanTransmitVendorSpecificAttribute; + +/* + Discovery Engine will forward any Vendor Specific Attributes + which it received as part of this structure. +*/ +/* Mask to determine on which frames attribute was received */ +#define RX_DISCOVERY_BEACON_MASK 0x01 +#define RX_SYNC_BEACON_MASK 0x02 +#define RX_SERVICE_DISCOVERY_MASK 0x04 +typedef struct { + /* + Frames on which this vendor specific attribute + was received. Mask defined above + */ + u8 vsa_received_on; + /* Organizationally Unique Identifier */ + u32 vendor_oui; + /* vendor specific attribute */ + u32 attr_len; + u8 vsa[NAN_MAX_VSA_DATA_LEN]; +} NanReceiveVendorSpecificAttribute; + +/* + NAN Beacon SDF Payload Received structure + Discovery engine sends the details of received Beacon or + Service Discovery Frames as part of this structure. +*/ +typedef struct { + /* Frame data */ + u32 frame_len; + u8 frame_data[NAN_MAX_FRAME_DATA_LEN]; +} NanBeaconSdfPayloadReceive; + +/* + Host can set the Periodic scan parameters for each of the + 3(6, 44, 149) Social channels. Only these channels are allowed + any other channels are rejected +*/ +typedef enum { + NAN_CHANNEL_24G_BAND = 0, + NAN_CHANNEL_5G_BAND_LOW, + NAN_CHANNEL_5G_BAND_HIGH +} NanChannelIndex; + +/* + Structure to set the Social Channel Scan parameters + passed as part of NanEnableRequest/NanConfigRequest +*/ +typedef struct { + /* + Dwell time of each social channel in milliseconds + NanChannelIndex corresponds to the respective channel + If time set to 0 then the FW default time will be used. + */ + u8 dwell_time[NAN_MAX_SOCIAL_CHANNELS]; // default value 200 msec + + /* + Scan period of each social channel in seconds + NanChannelIndex corresponds to the respective channel + If time set to 0 then the FW default time will be used. + */ + u16 scan_period[NAN_MAX_SOCIAL_CHANNELS]; // default value 20 sec +} NanSocialChannelScanParams; + +/* + Host can send Post Connectivity Capability attributes + to be included in Service Discovery frames transmitted + as part of this structure. +*/ +typedef struct { + /* + 0 = transmit only in the next discovery window + 1 = transmit in next 16 discovery window + */ + u8 payload_transmit_flag; + /* 1 - Wifi Direct supported 0 - Not supported */ + u8 is_wfd_supported; + /* 1 - Wifi Direct Services supported 0 - Not supported */ + u8 is_wfds_supported; + /* 1 - TDLS supported 0 - Not supported */ + u8 is_tdls_supported; + /* 1 - IBSS supported 0 - Not supported */ + u8 is_ibss_supported; + /* 1 - Mesh supported 0 - Not supported */ + u8 is_mesh_supported; + /* + 1 - NAN Device currently connect to WLAN Infra AP + 0 - otherwise + */ + u8 wlan_infra_field; +} NanTransmitPostConnectivityCapability; + +/* + Discovery engine providing the post connectivity capability + received. +*/ +typedef struct { + /* 1 - Wifi Direct supported 0 - Not supported */ + u8 is_wfd_supported; + /* 1 - Wifi Direct Services supported 0 - Not supported */ + u8 is_wfds_supported; + /* 1 - TDLS supported 0 - Not supported */ + u8 is_tdls_supported; + /* 1 - IBSS supported 0 - Not supported */ + u8 is_ibss_supported; + /* 1 - Mesh supported 0 - Not supported */ + u8 is_mesh_supported; + /* + 1 - NAN Device currently connect to WLAN Infra AP + 0 - otherwise + */ + u8 wlan_infra_field; +} NanReceivePostConnectivityCapability; + +/* + Indicates the availability interval duration associated with the + Availability Intervals Bitmap field +*/ +typedef enum { + NAN_DURATION_16MS = 0, + NAN_DURATION_32MS = 1, + NAN_DURATION_64MS = 2 +} NanAvailDuration; + +/* Further availability per channel information */ +typedef struct { + /* Defined above */ + NanAvailDuration entry_control; + /* + 1 byte field indicating the frequency band the NAN Device + will be available as defined in IEEE Std. 802.11-2012 + Annex E Table E-4 Global Operating Classes + */ + u8 class_val; + /* + 1 byte field indicating the channel the NAN Device + will be available. + */ + u8 channel; + /* + Map Id - 4 bit field which identifies the Further + availability map attribute. + */ + u8 mapid; + /* + divides the time between the beginnings of consecutive Discovery + Windows of a given NAN cluster into consecutive time intervals + of equal durations. The time interval duration is specified by + the Availability Interval Duration subfield of the Entry Control + field. + + A Nan device that sets the i-th bit of the Availability + Intervals Bitmap to 1 shall be present during the corresponding + i-th time interval in the operation channel indicated by the + Operating Class and Channel Number fields in the same Availability Entry. + + A Nan device that sets the i-th bit of the Availability Intervals Bitmap to + 0 may be present during the corresponding i-th time interval in the operation + channel indicated by the Operating Class and Channel Number fields in the same + Availability Entry. + + The size of the Bitmap is dependent upon the Availability Interval Duration + chosen in the Entry Control Field. The size can be either 1, 2 or 4 bytes long + + - Duration field is equal to 0, only AIB[0] is valid + - Duration field is equal to 1, only AIB [0] and AIB [1] is valid + - Duration field is equal to 2, AIB [0], AIB [1], AIB [2] and AIB [3] are valid + */ + u32 avail_interval_bitmap; +} NanFurtherAvailabilityChannel; + +/* + Further availability map which can be sent and received from + Discovery engine +*/ +typedef struct { + /* + Number of channels indicates the number of channel + entries which is part of fam + */ + u8 numchans; + NanFurtherAvailabilityChannel famchan[NAN_MAX_FAM_CHANNELS]; +} NanFurtherAvailabilityMap; + +/* + Host can send Post-Nan Discovery attributes which the Discovery Engine can + enclose in Service Discovery frames +*/ +/* Possible connection types in Post NAN Discovery attributes */ +typedef enum { + NAN_CONN_WLAN_INFRA = 0, + NAN_CONN_P2P_OPER = 1, + NAN_CONN_WLAN_IBSS = 2, + NAN_CONN_WLAN_MESH = 3, + NAN_CONN_FURTHER_SERVICE_AVAILABILITY = 4, + NAN_CONN_WLAN_RANGING = 5 +} NanConnectionType; + +/* Possible device roles in Post NAN Discovery attributes */ +typedef enum { + NAN_WLAN_INFRA_AP = 0, + NAN_WLAN_INFRA_STA = 1, + NAN_P2P_OPER_GO = 2, + NAN_P2P_OPER_DEV = 3, + NAN_P2P_OPER_CLI = 4 +} NanDeviceRole; + +/* Configuration params of NAN Ranging */ +typedef struct { + /* + Interval in milli sec between two ranging measurements. + If the Awake DW intervals in NanEnable/Config are larger + than the ranging intervals priority is given to Awake DW + Intervals. Only on a match the ranging is initiated for the + peer + */ + u32 ranging_interval_msec; + /* + Flags indicating the type of ranging event to be notified + NAN_RANGING_INDICATE_ MASKS are used to set these. + BIT0 - Continuous Ranging event notification. + BIT1 - Ingress distance is <=. + BIT2 - Egress distance is >=. + */ + u32 config_ranging_indications; + /* Ingress distance in millimeters (optional) */ + u32 distance_ingress_mm; + /* Egress distance in millmilliimeters (optional) */ + u32 distance_egress_mm; +} NanRangingCfg; + +/* NAN Ranging request's response */ +typedef struct { + /* Publish Id of an earlier Publisher */ + u16 publish_id; + /* + A 32 bit Requestor instance Id which is sent to the Application. + This Id will be used in subsequent RangeResponse on Subscribe side. + */ + u32 requestor_instance_id; + /* Peer MAC addr of Range Requestor */ + u8 peer_addr[NAN_MAC_ADDR_LEN]; + /* Response indicating ACCEPT/REJECT/CANCEL of Range Request */ + NanRangeResponse ranging_response; +} NanRangeResponseCfg; + +/* Structure of Post NAN Discovery attribute */ +typedef struct { + /* Connection type of the host */ + NanConnectionType type; + /* + Device role of the host based on + the connection type + */ + NanDeviceRole role; + /* + Flag to send the information as a single shot or repeated + for next 16 discovery windows + 0 - Single_shot + 1 - next 16 discovery windows + */ + u8 transmit_freq; + /* Duration of the availability bitmask */ + NanAvailDuration duration; + /* Availability interval bitmap based on duration */ + u32 avail_interval_bitmap; + /* + Mac address depending on the conn type and device role + -------------------------------------------------- + | Conn Type | Device Role | Mac address Usage | + -------------------------------------------------- + | WLAN_INFRA | AP/STA | BSSID of the AP | + -------------------------------------------------- + | P2P_OPER | GO | GO's address | + -------------------------------------------------- + | P2P_OPER | P2P_DEVICE | Address of who | + | | | would become GO | + -------------------------------------------------- + | WLAN_IBSS | NA | BSSID | + -------------------------------------------------- + | WLAN_MESH | NA | BSSID | + -------------------------------------------------- + */ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Mandatory mesh id value if connection type is WLAN_MESH + Mesh id contains 0-32 octet identifier and should be + as per IEEE Std.802.11-2012 spec. + */ + u16 mesh_id_len; + u8 mesh_id[NAN_MAX_MESH_DATA_LEN]; + /* + Optional infrastructure SSID if conn_type is set to + NAN_CONN_WLAN_INFRA + */ + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[NAN_MAX_INFRA_DATA_LEN]; +} NanTransmitPostDiscovery; + +/* + Discovery engine providing the structure of Post NAN + Discovery +*/ +typedef struct { + /* Connection type of the host */ + NanConnectionType type; + /* + Device role of the host based on + the connection type + */ + NanDeviceRole role; + /* Duration of the availability bitmask */ + NanAvailDuration duration; + /* Availability interval bitmap based on duration */ + u32 avail_interval_bitmap; + /* + Map Id - 4 bit field which identifies the Further + availability map attribute. + */ + u8 mapid; + /* + Mac address depending on the conn type and device role + -------------------------------------------------- + | Conn Type | Device Role | Mac address Usage | + -------------------------------------------------- + | WLAN_INFRA | AP/STA | BSSID of the AP | + -------------------------------------------------- + | P2P_OPER | GO | GO's address | + -------------------------------------------------- + | P2P_OPER | P2P_DEVICE | Address of who | + | | | would become GO | + -------------------------------------------------- + | WLAN_IBSS | NA | BSSID | + -------------------------------------------------- + | WLAN_MESH | NA | BSSID | + -------------------------------------------------- + */ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Mandatory mesh id value if connection type is WLAN_MESH + Mesh id contains 0-32 octet identifier and should be + as per IEEE Std.802.11-2012 spec. + */ + u16 mesh_id_len; + u8 mesh_id[NAN_MAX_MESH_DATA_LEN]; + /* + Optional infrastructure SSID if conn_type is set to + NAN_CONN_WLAN_INFRA + */ + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[NAN_MAX_INFRA_DATA_LEN]; +} NanReceivePostDiscovery; + +/* + NAN device level configuration of SDF and Sync beacons in both + 2.4/5GHz bands +*/ +typedef struct { + /* Configure 2.4GHz DW Band */ + u8 config_2dot4g_dw_band; + /* + Indicates the interval for Sync beacons and SDF's in 2.4GHz band. + Valid values of DW Interval are: 1, 2, 3, 4 and 5, 0 is reserved. + The SDF includes in OTA when enabled. The publish/subscribe period + values don't override the device level configurations. + */ + u32 dw_2dot4g_interval_val; // default value 1 + /* Configure 5GHz DW Band */ + u8 config_5g_dw_band; + /* + Indicates the interval for Sync beacons and SDF's in 5GHz band + Valid values of DW Interval are: 1, 2, 3, 4 and 5, 0 no wake up for + any interval. The SDF includes in OTA when enabled. The publish/subscribe + period values don't override the device level configurations. + */ + u32 dw_5g_interval_val; // default value 1 when 5G is enabled +} NanConfigDW; + +/* + Enable Request Message Structure + The NanEnableReq message instructs the Discovery Engine to enter an operational state +*/ +typedef struct { + /* Mandatory parameters below */ + u8 master_pref; // default value 0x02 + /* + A cluster_low value matching cluster_high indicates a request to join + a cluster with that value. If the requested cluster is not found the + device will start its own cluster. + */ + u16 cluster_low; // default value 0 + u16 cluster_high; // default value 0xFFFF + + /* + Optional configuration of Enable request. + Each of the optional parameters have configure flag which + determine whether configuration is to be passed or not. + */ + u8 config_support_5g; + u8 support_5g_val; // default value 0; turned off by default + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_sid_beacon; + u8 sid_beacon_val; // default value 0x01 + /* + The rssi values below should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_2dot4g_rssi_close; + u8 rssi_close_2dot4g_val; // default value -60 dBm + + u8 config_2dot4g_rssi_middle; + u8 rssi_middle_2dot4g_val; // default value -70 dBm + + u8 config_2dot4g_rssi_proximity; + u8 rssi_proximity_2dot4g_val; // default value -60dBm + + u8 config_hop_count_limit; + u8 hop_count_limit_val; // default value 0x02 + + /* + Defines 2.4G channel access support + 0 - No Support + 1 - Supported + */ + u8 config_2dot4g_support; + u8 support_2dot4g_val; // default value 0x01 + /* + Defines 2.4G channels will be used for sync/discovery beacons + 0 - 2.4G channels not used for beacons + 1 - 2.4G channels used for beacons + */ + u8 config_2dot4g_beacons; + u8 beacon_2dot4g_val; // default value 1 + /* + Defines 2.4G channels will be used for Service Discovery frames + 0 - 2.4G channels not used for Service Discovery frames + 1 - 2.4G channels used for Service Discovery frames + */ + u8 config_2dot4g_sdf; + u8 sdf_2dot4g_val; // default value 1 + /* + Defines 5G channels will be used for sync/discovery beacons + 0 - 5G channels not used for beacons + 1 - 5G channels used for beacons + */ + u8 config_5g_beacons; + u8 beacon_5g_val; // default value 1 when 5G is enabled + /* + Defines 5G channels will be used for Service Discovery frames + 0 - 5G channels not used for Service Discovery frames + 1 - 5G channels used for Service Discovery frames + */ + u8 config_5g_sdf; + u8 sdf_5g_val; // default value is 0 when 5G is enabled + /* + 1 byte value which defines the RSSI in + dBm for a close by Peer in 5 Ghz channels. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close; + u8 rssi_close_5g_val; // default value -60dBm when 5G is enabled + /* + 1 byte value which defines the RSSI value in + dBm for a close by Peer in 5 Ghz channels. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_middle; + u8 rssi_middle_5g_val; // default value -75dBm when 5G is enabled + /* + 1 byte value which defines the RSSI filter + threshold. Any Service Descriptors received above this + value that are configured for RSSI filtering will be dropped. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; // default value -60dBm when 5G is enabled + /* + 1 byte quantity which defines the window size over + which the “average RSSI” will be calculated over. + */ + u8 config_rssi_window_size; + u8 rssi_window_size_val; // default value 0x08 + /* + The 24 bit Organizationally Unique ID + the 8 bit Network Id. + */ + u8 config_oui; + u32 oui_val; // default value {0x51, 0x6F, 0x9A, 0x01, 0x00, 0x00} + /* + NAN Interface Address, If not configured the Discovery Engine + will generate a 6 byte Random MAC. + */ + u8 config_intf_addr; + u8 intf_addr_val[NAN_MAC_ADDR_LEN]; + /* + If set to 1, the Discovery Engine will enclose the Cluster + Attribute only sent in Beacons in a Vendor Specific Attribute + and transmit in a Service Descriptor Frame. + */ + u8 config_cluster_attribute_val; + /* + The periodicity in seconds between full scan’s to find any new + clusters available in the area. A Full scan should not be done + more than every 10 seconds and should not be done less than every + 30 seconds. + */ + u8 config_scan_params; + NanSocialChannelScanParams scan_params_val; + /* + 1 byte quantity which forces the Random Factor to a particular + value for all transmitted Sync/Discovery beacons + */ + u8 config_random_factor_force; + u8 random_factor_force_val; // default value off and set to 0x00 + /* + 1 byte quantity which forces the HC for all transmitted Sync and + Discovery Beacon NO matter the real HC being received over the + air. + */ + u8 config_hop_count_force; + u8 hop_count_force_val; // default value 0x00 + + /* channel frequency in MHz to enable Nan on */ + u8 config_24g_channel; + wifi_channel channel_24g_val; // default value channel 0x6 + + u8 config_5g_channel; + wifi_channel channel_5g_val; // default value channel 44 or 149 regulatory + // domain + /* Configure 2.4/5GHz DW */ + NanConfigDW config_dw; + + /* + By default discovery MAC address randomization is enabled + and default interval value is 30 minutes i.e. 1800 seconds. + The value 0 is used to disable MAC addr randomization. + */ + u8 config_disc_mac_addr_randomization; + u32 disc_mac_addr_rand_interval_sec; // default value 1800 sec + + /* + Set/Enable corresponding bits to disable Discovery indications: + BIT0 - Disable Discovery MAC Address Event. + BIT1 - Disable Started Cluster Event. + BIT2 - Disable Joined Cluster Event. + */ + u8 discovery_indication_cfg; // default value 0x0 + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_subscribe_sid_beacon; + u32 subscribe_sid_beacon_val; // default value 0x0 + /* + Discovery Beacon Interval config. + Default value is 128 msec in 2G DW and 176 msec in 2G/5G DW. + When 0 value is passed it is reset to default value of 128 or 176 msec. + */ + u8 config_discovery_beacon_int; + u32 discovery_beacon_interval; + /* + Enable Number of Spatial Streams. + This is NAN Power Optimization feature for NAN discovery. + */ + u8 config_nss; + // default value is implementation specific and passing 0 sets it to default + u32 nss; + /* + Enable device level NAN Ranging feature. + 0 - Disable + 1 - Enable + */ + u8 config_enable_ranging; + u32 enable_ranging; + /* + Enable/Disable DW Early termination. + 0 - Disable + 1 - Enable + */ + u8 config_dw_early_termination; + u32 enable_dw_termination; + /* + Indicate whether to use NDPE attribute to bring-up TCP/IP connection. + If config_ndpe_attr is not configured, the default behavior is + not using NDPE attr, and the capability is not advertised. + 0 - Not use + 1 - Use + */ + u8 config_ndpe_attr; + u32 use_ndpe_attr; + /* + Enable NAN v3.1 instant communication mode. + 0 - Disable + 1 - Enable + */ + u8 config_enable_instant_mode; + u32 enable_instant_mode; + /* + Config NAN v3.1 instant communication channel frequency selected over NFC/OOB method. + If dual band is supported default channel is 149 or 44 as per regulatory domain, + else channel 6 (send frequency in MHz). + Sometimes depending on country code retrictions, even 149/44 may be restricted + in those cases instant channel will be operational only in 2.4GHz. + Use wifi_get_usable_channels() API to get supported bands/channels before + Instant mode NFC handshake is triggered + */ + u8 config_instant_mode_channel; + wifi_channel instant_mode_channel; +} NanEnableRequest; + +/* + Publish Msg Structure + Message is used to request the DE to publish the Service Name + using the parameters passed into the Discovery Window +*/ +typedef struct { + u16 publish_id; /* id 0 means new publish, any other id is existing publish */ + u16 ttl; /* how many seconds to run for. 0 means forever until canceled */ + /* + period: Awake DW Interval for publish(service) + Indicates the interval between two Discovery Windows in which + the device supporting the service is awake to transmit or + receive the Service Discovery frames. + Valid values of Awake DW Interval are: 1, 2, 4, 8 and 16, value 0 will + default to 1. + */ + u16 period; + NanPublishType publish_type; /* 0= unsolicited, solicited = 1, 2= both */ + NanTxType tx_type; /* 0 = broadcast, 1= unicast if solicited publish */ + u8 publish_count; /* number of OTA Publish, 0 means forever until canceled */ + u16 service_name_len; /* length of service name */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; /* UTF-8 encoded string identifying the service */ + /* + Field which specifies how the matching indication to host is controlled. + 0 - Match and Indicate Once + 1 - Match and Indicate continuous + 2 - Match and Indicate never. This means don't indicate the match to the host. + 3 - Reserved + */ + NanMatchAlg publish_match_indicator; + + /* + Sequence of values + NAN Device that has invoked a Subscribe method corresponding to this Publish method + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of <length, value> pairs which specify further response conditions + beyond the service name used to filter subscribe messages to respond to. + This is only needed when the PT is set to NAN_SOLICITED or NAN_SOLICITED_UNSOLICITED. + */ + u16 rx_match_filter_len; + u8 rx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Ordered sequence of <length, value> pairs to be included in the Discovery Frame. + If present it is always sent in a Discovery Frame + */ + u16 tx_match_filter_len; + u8 tx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + flag which specifies that the Publish should use the configured RSSI + threshold and the received RSSI in order to filter requests + 0 – ignore the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + 1 – use the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + + */ + u8 rssi_threshold_flag; + + /* + 8-bit bitmap which allows the Host to associate this publish + with a particular Post-NAN Connectivity attribute + which has been sent down in a NanConfigureRequest/NanEnableRequest + message. If the DE fails to find a configured Post-NAN + connectivity attributes referenced by the bitmap, + the DE will return an error code to the Host. + If the Publish is configured to use a Post-NAN Connectivity + attribute and the Host does not refresh the Post-NAN Connectivity + attribute the Publish will be canceled and the Host will be sent + a PublishTerminatedIndication message. + */ + u8 connmap; + /* + Set/Enable corresponding bits to disable any indications that follow a publish. + BIT0 - Disable publish termination indication. + BIT1 - Disable match expired indication. + BIT2 - Disable followUp indication received (OTA). + BIT3 - Disable publishReplied indication. + */ + u8 recv_indication_cfg; + /* + Nan accept policy for the specific service(publish) + */ + NanServiceAcceptPolicy service_responder_policy; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* NAN configure service discovery extended attributes */ + NanSdeaCtrlParams sdea_params; + + /* NAN Ranging configuration */ + NanRangingCfg ranging_cfg; + + /* Enable/disable NAN serivce Ranging auto response mode */ + NanRangingAutoResponse ranging_auto_response; + + /* + When the ranging_auto_response_cfg is not set, NanRangeRequestInd is + received. Nan Range Response to Peer MAC Addr is notified to indicate + ACCEPT/REJECT/CANCEL to the requestor. + */ + NanRangeResponseCfg range_response_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanPublishRequest; + +/* + Publish Cancel Msg Structure + The PublishServiceCancelReq Message is used to request the DE to stop publishing + the Service Name identified by the Publish Id in the message. +*/ +typedef struct { + u16 publish_id; +} NanPublishCancelRequest; + +/* + NAN Subscribe Structure + The SubscribeServiceReq message is sent to the Discovery Engine + whenever the Upper layers would like to listen for a Service Name +*/ +typedef struct { + u16 subscribe_id; /* id 0 means new subscribe, non zero is existing subscribe */ + u16 ttl; /* how many seconds to run for. 0 means forever until canceled */ + /* + period: Awake DW Interval for subscribe(service) + Indicates the interval between two Discovery Windows in which + the device supporting the service is awake to transmit or + receive the Service Discovery frames. + Valid values of Awake DW Interval are: 1, 2, 4, 8 and 16, value 0 will + default to 1. + */ + u16 period; + + /* Flag which specifies how the Subscribe request shall be processed. */ + NanSubscribeType subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */ + + /* Flag which specifies on Active Subscribes how the Service Response Filter attribute is + * populated.*/ + NanSRFType serviceResponseFilter; /* 0 - Bloom Filter, 1 - MAC Addr */ + + /* Flag which specifies how the Service Response Filter Include bit is populated.*/ + NanSRFIncludeType + serviceResponseInclude; /* 0=Do not respond if in the Address Set, 1= Respond */ + + /* Flag which specifies if the Service Response Filter should be used when creating + * Subscribes.*/ + NanSRFState useServiceResponseFilter; /* 0=Do not send the Service Response Filter,1= send */ + + /* + Flag which specifies if the Service Specific Info is needed in + the Publish message before creating the MatchIndication + */ + NanSsiInMatchInd ssiRequiredForMatchIndication; /* 0=Not needed, 1= Required */ + + /* + Field which specifies how the matching indication to host is controlled. + 0 - Match and Indicate Once + 1 - Match and Indicate continuous + 2 - Match and Indicate never. This means don't indicate the match to the host. + 3 - Reserved + */ + NanMatchAlg subscribe_match_indicator; + + /* + The number of Subscribe Matches which should occur + before the Subscribe request is automatically terminated. + */ + u8 subscribe_count; /* If this value is 0 this field is not used by the DE.*/ + + u16 service_name_len; /* length of service name */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; /* UTF-8 encoded string identifying the service */ + + /* Sequence of values which further specify the published service beyond the service name*/ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of <length, value> pairs used to filter out received publish discovery + messages. This can be sent both for a Passive or an Active Subscribe + */ + u16 rx_match_filter_len; + u8 rx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Ordered sequence of <length, value> pairs included in the + Discovery Frame when an Active Subscribe is used. + */ + u16 tx_match_filter_len; + u8 tx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Flag which specifies that the Subscribe should use the configured RSSI + threshold and the received RSSI in order to filter requests + 0 – ignore the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + 1 – use the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + + */ + u8 rssi_threshold_flag; + + /* + 8-bit bitmap which allows the Host to associate this Active + Subscribe with a particular Post-NAN Connectivity attribute + which has been sent down in a NanConfigureRequest/NanEnableRequest + message. If the DE fails to find a configured Post-NAN + connectivity attributes referenced by the bitmap, + the DE will return an error code to the Host. + If the Subscribe is configured to use a Post-NAN Connectivity + attribute and the Host does not refresh the Post-NAN Connectivity + attribute the Subscribe will be canceled and the Host will be sent + a SubscribeTerminatedIndication message. + */ + u8 connmap; + /* + NAN Interface Address, conforming to the format as described in + 8.2.4.3.2 of IEEE Std. 802.11-2012. + */ + u8 num_intf_addr_present; + u8 intf_addr[NAN_MAX_SUBSCRIBE_MAX_ADDRESS][NAN_MAC_ADDR_LEN]; + /* + Set/Enable corresponding bits to disable indications that follow a subscribe. + BIT0 - Disable subscribe termination indication. + BIT1 - Disable match expired indication. + BIT2 - Disable followUp indication received (OTA). + */ + u8 recv_indication_cfg; + + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* NAN configure service discovery extended attributes */ + NanSdeaCtrlParams sdea_params; + + /* NAN Ranging configuration */ + NanRangingCfg ranging_cfg; + + /* Enable/disable NAN serivce Ranging auto response mode */ + NanRangingAutoResponse ranging_auto_response; + + /* + When the ranging_auto_response_cfg is not set, NanRangeRequestInd is + received. Nan Range Response to Peer MAC Addr is notified to indicate + ACCEPT/REJECT/CANCEL to the requestor. + */ + NanRangeResponseCfg range_response_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanSubscribeRequest; + +/* + NAN Subscribe Cancel Structure + The SubscribeCancelReq Message is used to request the DE to stop looking for the Service Name. +*/ +typedef struct { + u16 subscribe_id; +} NanSubscribeCancelRequest; + +/* + Transmit follow up Structure + The TransmitFollowupReq message is sent to the DE to allow the sending of the + Service_Specific_Info to a particular MAC address. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + + /* + This Id is the Requestor Instance that is passed as + part of earlier MatchInd/FollowupInd message. + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; /* Unicast address */ + NanTxPriority priority; /* priority of the request 2=high */ + NanTransmitWindowType dw_or_faw; /* 0= send in a DW, 1=send in FAW */ + + /* + Sequence of values which further specify the published service beyond + the service name. + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + /* + Set/Enable corresponding bits to disable responses after followUp. + BIT0 - Disable followUp response from FW. + */ + u8 recv_indication_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanTransmitFollowupRequest; + +/* + Stats Request structure + The Discovery Engine can be queried at runtime by the Host processor for statistics + concerning various parts of the Discovery Engine. +*/ +typedef struct { + NanStatsType stats_type; /* NAN Statistics Request Type */ + u8 clear; /* 0= Do not clear the stats and return the current contents , 1= Clear the associated + stats */ +} NanStatsRequest; + +/* + Config Structure + The NanConfigurationReq message is sent by the Host to the + Discovery Engine in order to configure the Discovery Engine during runtime. +*/ +typedef struct { + u8 config_sid_beacon; + u8 sid_beacon; + u8 config_rssi_proximity; + u8 rssi_proximity; // default value -60dBm + u8 config_master_pref; + u8 master_pref; // default value 0x02 + /* + 1 byte value which defines the RSSI filter threshold. + Any Service Descriptors received above this value + that are configured for RSSI filtering will be dropped. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; // default value -60dBm + /* + Optional configuration of Configure request. + Each of the optional parameters have configure flag which + determine whether configuration is to be passed or not. + */ + /* + 1 byte quantity which defines the window size over + which the “average RSSI” will be calculated over. + */ + u8 config_rssi_window_size; + u8 rssi_window_size_val; // default value 0x08 + /* + If set to 1, the Discovery Engine will enclose the Cluster + Attribute only sent in Beacons in a Vendor Specific Attribute + and transmit in a Service Descriptor Frame. + */ + u8 config_cluster_attribute_val; + /* + The periodicity in seconds between full scan’s to find any new + clusters available in the area. A Full scan should not be done + more than every 10 seconds and should not be done less than every + 30 seconds. + */ + u8 config_scan_params; + NanSocialChannelScanParams scan_params_val; + /* + 1 byte quantity which forces the Random Factor to a particular + value for all transmitted Sync/Discovery beacons + */ + u8 config_random_factor_force; + u8 random_factor_force_val; // default value 0x00 + /* + 1 byte quantity which forces the HC for all transmitted Sync and + Discovery Beacon NO matter the real HC being received over the + air. + */ + u8 config_hop_count_force; + u8 hop_count_force_val; // default value of 0 + /* NAN Post Connectivity Capability */ + u8 config_conn_capability; + NanTransmitPostConnectivityCapability conn_capability_val; + /* NAN Post Discover Capability */ + u8 num_config_discovery_attr; + NanTransmitPostDiscovery discovery_attr_val[NAN_MAX_POSTDISCOVERY_LEN]; + /* NAN Further availability Map */ + u8 config_fam; + NanFurtherAvailabilityMap fam_val; + /* Configure 2.4/5GHz DW */ + NanConfigDW config_dw; + /* + By default discovery MAC address randomization is enabled + and default interval value is 30 minutes i.e. 1800 seconds. + The value 0 is used to disable MAC addr randomization. + */ + u8 config_disc_mac_addr_randomization; + u32 disc_mac_addr_rand_interval_sec; // default value of 30 minutes + + /* + Set/Enable corresponding bits to disable Discovery indications: + BIT0 - Disable Discovery MAC Address Event. + BIT1 - Disable Started Cluster Event. + BIT2 - Disable Joined Cluster Event. + */ + u8 discovery_indication_cfg; // default value of 0 + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_subscribe_sid_beacon; + u32 subscribe_sid_beacon_val; // default value 0x0 + /* + Discovery Beacon Interval config. + Default value is 128 msec in 2G DW and 176 msec in 2G/5G DW. + When 0 value is passed it is reset to default value of 128 or 176 msec. + */ + u8 config_discovery_beacon_int; + u32 discovery_beacon_interval; + /* + Enable Number of Spatial Streams. + This is NAN Power Optimization feature for NAN discovery. + */ + u8 config_nss; + // default value is implementation specific and passing 0 sets it to default + u32 nss; + /* + Enable device level NAN Ranging feature. + 0 - Disable + 1 - Enable + */ + u8 config_enable_ranging; + u32 enable_ranging; + /* + Enable/Disable DW Early termination. + 0 - Disable + 1 - Enable + */ + u8 config_dw_early_termination; + u32 enable_dw_termination; + /* + Indicate whether to use NDPE attribute to bring-up TCP/IP connection + If config_ndpe_attr is not configured, the default behavior is + not using NDPE attr, and the capability is not advertised. + 0 - Not use + 1 - Use + */ + u8 config_ndpe_attr; + u32 use_ndpe_attr; + /* + Enable NAN v3.1 instant communication mode. + 0 - Disable + 1 - Enable + */ + u8 config_enable_instant_mode; + u32 enable_instant_mode; + /* + Config NAN v3.1 instant communication channel selected over NFC/OOB method. + If dual band is supported default channel is 149 or 44 as per regulatory domain, + else channel 6 (send frequency in MHz). + Sometimes depending on country code retrictions, even 149/44 may be restricted + in those cases instant channel will be operational only in 2.4GHz. + Use wifi_get_usable_channels() API to get supported bands/channels before + Instant mode NFC handshake is triggered + */ + u8 config_instant_mode_channel; + wifi_channel instant_mode_channel; +} NanConfigRequest; + +/* + TCA Structure + The Discovery Engine can be configured to send up Events whenever a configured + Threshold Crossing Alert (TCA) Type crosses an integral threshold in a particular direction. +*/ +typedef struct { + NanTcaType tca_type; /* Nan Protocol Threshold Crossing Alert (TCA) Codes */ + + /* flag which control whether or not an event is generated for the Rising direction */ + u8 rising_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which control whether or not an event is generated for the Falling direction */ + u8 falling_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which requests a previous TCA request to be cleared from the DE */ + u8 clear; /*0= Do not clear the TCA, 1=Clear the TCA */ + + /* 32 bit value which represents the threshold to be used.*/ + u32 threshold; +} NanTCARequest; + +/* + Beacon Sdf Payload Structure + The Discovery Engine can be configured to publish vendor specific attributes as part of + beacon or service discovery frame transmitted as part of this request.. +*/ +typedef struct { + /* + NanVendorAttribute will have the Vendor Specific Attribute which the + vendor wants to publish as part of Discovery or Sync or Service discovery frame + */ + NanTransmitVendorSpecificAttribute vsa; +} NanBeaconSdfPayloadRequest; + +/* Publish statistics. */ +typedef struct { + u32 validPublishServiceReqMsgs; + u32 validPublishServiceRspMsgs; + u32 validPublishServiceCancelReqMsgs; + u32 validPublishServiceCancelRspMsgs; + u32 validPublishRepliedIndMsgs; + u32 validPublishTerminatedIndMsgs; + u32 validActiveSubscribes; + u32 validMatches; + u32 validFollowups; + u32 invalidPublishServiceReqMsgs; + u32 invalidPublishServiceCancelReqMsgs; + u32 invalidActiveSubscribes; + u32 invalidMatches; + u32 invalidFollowups; + u32 publishCount; + u32 publishNewMatchCount; + u32 pubsubGlobalNewMatchCount; +} NanPublishStats; + +/* Subscribe statistics. */ +typedef struct { + u32 validSubscribeServiceReqMsgs; + u32 validSubscribeServiceRspMsgs; + u32 validSubscribeServiceCancelReqMsgs; + u32 validSubscribeServiceCancelRspMsgs; + u32 validSubscribeTerminatedIndMsgs; + u32 validSubscribeMatchIndMsgs; + u32 validSubscribeUnmatchIndMsgs; + u32 validSolicitedPublishes; + u32 validMatches; + u32 validFollowups; + u32 invalidSubscribeServiceReqMsgs; + u32 invalidSubscribeServiceCancelReqMsgs; + u32 invalidSubscribeFollowupReqMsgs; + u32 invalidSolicitedPublishes; + u32 invalidMatches; + u32 invalidFollowups; + u32 subscribeCount; + u32 bloomFilterIndex; + u32 subscribeNewMatchCount; + u32 pubsubGlobalNewMatchCount; +} NanSubscribeStats; + +/* NAN DW Statistics*/ +typedef struct { + /* RX stats */ + u32 validFrames; + u32 validActionFrames; + u32 validBeaconFrames; + u32 ignoredActionFrames; + u32 ignoredBeaconFrames; + u32 invalidFrames; + u32 invalidActionFrames; + u32 invalidBeaconFrames; + u32 invalidMacHeaders; + u32 invalidPafHeaders; + u32 nonNanBeaconFrames; + + u32 earlyActionFrames; + u32 inDwActionFrames; + u32 lateActionFrames; + + /* TX stats */ + u32 framesQueued; + u32 totalTRSpUpdates; + u32 completeByTRSp; + u32 completeByTp75DW; + u32 completeByTendDW; + u32 lateActionFramesTx; +} NanDWStats; + +/* NAN MAC Statistics. */ +typedef struct { + /* RX stats */ + u32 validFrames; + u32 validActionFrames; + u32 validBeaconFrames; + u32 ignoredActionFrames; + u32 ignoredBeaconFrames; + u32 invalidFrames; + u32 invalidActionFrames; + u32 invalidBeaconFrames; + u32 invalidMacHeaders; + u32 invalidPafHeaders; + u32 nonNanBeaconFrames; + + u32 earlyActionFrames; + u32 inDwActionFrames; + u32 lateActionFrames; + + /* TX stats */ + u32 framesQueued; + u32 totalTRSpUpdates; + u32 completeByTRSp; + u32 completeByTp75DW; + u32 completeByTendDW; + u32 lateActionFramesTx; + + u32 twIncreases; + u32 twDecreases; + u32 twChanges; + u32 twHighwater; + u32 bloomFilterIndex; +} NanMacStats; + +/* NAN Sync Statistics*/ +typedef struct { + u64 currTsf; + u64 myRank; + u64 currAmRank; + u64 lastAmRank; + u32 currAmBTT; + u32 lastAmBTT; + u8 currAmHopCount; + u8 currRole; + u16 currClusterId; + + u64 timeSpentInCurrRole; + u64 totalTimeSpentAsMaster; + u64 totalTimeSpentAsNonMasterSync; + u64 totalTimeSpentAsNonMasterNonSync; + u32 transitionsToAnchorMaster; + u32 transitionsToMaster; + u32 transitionsToNonMasterSync; + u32 transitionsToNonMasterNonSync; + u32 amrUpdateCount; + u32 amrUpdateRankChangedCount; + u32 amrUpdateBTTChangedCount; + u32 amrUpdateHcChangedCount; + u32 amrUpdateNewDeviceCount; + u32 amrExpireCount; + u32 mergeCount; + u32 beaconsAboveHcLimit; + u32 beaconsBelowRssiThresh; + u32 beaconsIgnoredNoSpace; + u32 beaconsForOurCluster; + u32 beaconsForOtherCluster; + u32 beaconCancelRequests; + u32 beaconCancelFailures; + u32 beaconUpdateRequests; + u32 beaconUpdateFailures; + u32 syncBeaconTxAttempts; + u32 syncBeaconTxFailures; + u32 discBeaconTxAttempts; + u32 discBeaconTxFailures; + u32 amHopCountExpireCount; + u32 ndpChannelFreq; + u32 ndpChannelFreq2; + u32 schedUpdateChannelFreq; +} NanSyncStats; + +/* NAN Misc DE Statistics */ +typedef struct { + u32 validErrorRspMsgs; + u32 validTransmitFollowupReqMsgs; + u32 validTransmitFollowupRspMsgs; + u32 validFollowupIndMsgs; + u32 validConfigurationReqMsgs; + u32 validConfigurationRspMsgs; + u32 validStatsReqMsgs; + u32 validStatsRspMsgs; + u32 validEnableReqMsgs; + u32 validEnableRspMsgs; + u32 validDisableReqMsgs; + u32 validDisableRspMsgs; + u32 validDisableIndMsgs; + u32 validEventIndMsgs; + u32 validTcaReqMsgs; + u32 validTcaRspMsgs; + u32 validTcaIndMsgs; + u32 invalidTransmitFollowupReqMsgs; + u32 invalidConfigurationReqMsgs; + u32 invalidStatsReqMsgs; + u32 invalidEnableReqMsgs; + u32 invalidDisableReqMsgs; + u32 invalidTcaReqMsgs; +} NanDeStats; + +/* Publish Response Message structure */ +typedef struct { + u16 publish_id; +} NanPublishResponse; + +/* Subscribe Response Message structure */ +typedef struct { + u16 subscribe_id; +} NanSubscribeResponse; + +/* + Stats Response Message structure + The Discovery Engine response to a request by the Host for statistics. +*/ +typedef struct { + NanStatsType stats_type; + union { + NanPublishStats publish_stats; + NanSubscribeStats subscribe_stats; + NanMacStats mac_stats; + NanSyncStats sync_stats; + NanDeStats de_stats; + NanDWStats dw_stats; + } data; +} NanStatsResponse; + +/* Response returned for Initiators Data request */ +typedef struct { + /* + Unique token Id generated on the initiator + side used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; +} NanDataPathRequestResponse; + +/* + NAN Response messages +*/ +typedef struct { + NanStatusType status; /* contains the result code */ + char nan_error[NAN_ERROR_STR_LEN]; /* Describe the NAN error type */ + NanResponseType response_type; /* NanResponseType Definitions */ + union { + NanPublishResponse publish_response; + NanSubscribeResponse subscribe_response; + NanStatsResponse stats_response; + NanDataPathRequestResponse data_request_response; + NanCapabilities nan_capabilities; + } body; +} NanResponseMsg; + +/* + Publish Replied Indication + The PublishRepliedInd Message is sent by the DE when an Active Subscribe is + received over the air and it matches a Solicited PublishServiceReq which had + been created with the replied_event_flag set. +*/ +typedef struct { + /* + A 32 bit Requestor Instance Id which is sent to the Application. + This Id will be sent in any subsequent UnmatchInd/FollowupInd + messages + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + /* + If RSSI filtering was configured in NanPublishRequest then this + field will contain the received RSSI value. 0 if not + */ + u8 rssi_value; +} NanPublishRepliedInd; + +/* + Publish Terminated + The PublishTerminatedInd message is sent by the DE whenever a Publish + terminates from a user-specified timeout or a unrecoverable error in the DE. +*/ +typedef struct { + /* Id returned during the initial Publish */ + u16 publish_id; + /* + For all user configured termination NAN_STATUS_SUCCESS + and no other reasons expected from firmware. + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanPublishTerminatedInd; + +/* + Match Indication + The MatchInd message is sent once per responding MAC address whenever + the Discovery Engine detects a match for a previous SubscribeServiceReq + or PublishServiceReq. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + A 32 bit Requestor Instance Id which is sent to the Application. + This Id will be sent in any subsequent UnmatchInd/FollowupInd + messages + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + + /* + Sequence of octets which were received in a Discovery Frame matching the + Subscribe Request. + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of <length, value> pairs received in the Discovery Frame + matching the Subscribe Request. + */ + u16 sdf_match_filter_len; + u8 sdf_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + flag to indicate if the Match occurred in a Beacon Frame or in a + Service Discovery Frame. + 0 - Match occured in a Service Discovery Frame + 1 - Match occured in a Beacon Frame + */ + u8 match_occured_flag; + + /* + flag to indicate FW is out of resource and that it can no longer + track this Service Name. The Host still need to send the received + Match_Handle but duplicate MatchInd messages may be received on + this Handle until the resource frees up. + 0 - FW is caching this match + 1 - FW is unable to cache this match + */ + u8 out_of_resource_flag; + + /* + If RSSI filtering was configured in NanSubscribeRequest then this + field will contain the received RSSI value. 0 if not. + All rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 rssi_value; + + /* + optional attributes. Each optional attribute is associated with a flag + which specifies whether the attribute is valid or not + */ + /* NAN Post Connectivity Capability received */ + u8 is_conn_capability_valid; + NanReceivePostConnectivityCapability conn_capability; + + /* NAN Post Discover Capability */ + u8 num_rx_discovery_attr; + NanReceivePostDiscovery discovery_attr[NAN_MAX_POSTDISCOVERY_LEN]; + + /* NAN Further availability Map */ + u8 num_chans; + NanFurtherAvailabilityChannel famchan[NAN_MAX_FAM_CHANNELS]; + + /* NAN Cluster Attribute */ + u8 cluster_attribute_len; + u8 cluster_attribute[NAN_MAX_CLUSTER_ATTRIBUTE_LEN]; + + /* NAN Cipher Suite */ + u32 peer_cipher_type; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* Peer service discovery extended attributes */ + NanSdeaCtrlParams peer_sdea_params; + + /* + Ranging indication and NanMatchAlg are not tied. + Ex: NanMatchAlg can indicate Match_ONCE, but ranging + indications can be continuous. All ranging indications + depend on SDEA control parameters of ranging required for + continuous, and ingress/egress values in the ranging config. + Ranging indication data is notified if: + 1) Ranging required is enabled in SDEA. + range info notified continuous. + 2) if range_limit ingress/egress MASKS are enabled + notify once for ingress >= ingress_distance + and egress <= egress_distance, same for ingress_egress_both + 3) if the Awake DW intervals are higher than the ranging intervals, + priority is given to the device DW intervalsi. + */ + /* + Range Info includes: + 1) distance to the NAN device with the MAC address indicated + with ranged mac address. + 2) Ranging event matching the configuration of continuous/ingress/egress. + */ + NanRangeInfo range_info; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanMatchInd; + +/* + MatchExpired Indication + The MatchExpiredInd message is sent whenever the Discovery Engine detects that + a previously Matched Service has been gone for too long. If the previous + MatchInd message for this Publish/Subscribe Id had the out_of_resource_flag + set then this message will not be received +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + 32 bit value sent by the DE in a previous + MatchInd/FollowupInd to the application. + */ + u32 requestor_instance_id; +} NanMatchExpiredInd; + +/* + Subscribe Terminated + The SubscribeTerminatedInd message is sent by the DE whenever a + Subscribe terminates from a user-specified timeout or a unrecoverable error in the DE. +*/ +typedef struct { + /* Id returned during initial Subscribe */ + u16 subscribe_id; + /* + For all user configured termination NAN_STATUS_SUCCESS + and no other reasons expected from firmware. + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanSubscribeTerminatedInd; + +/* + Followup Indication Message + The FollowupInd message is sent by the DE to the Host whenever it receives a + Followup message from another peer. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + A 32 bit Requestor instance Id which is sent to the Application. + This Id will be used in subsequent UnmatchInd/FollowupInd messages. + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + + /* Flag which the DE uses to decide if received in a DW or a FAW*/ + u8 dw_or_faw; /* 0=Received in a DW, 1 = Received in a FAW*/ + + /* + Sequence of values which further specify the published service beyond + the service name + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanFollowupInd; + +/* + Event data notifying the Mac address of the Discovery engine. + which is reported as one of the Discovery engine event +*/ +typedef struct { + u8 addr[NAN_MAC_ADDR_LEN]; +} NanMacAddressEvent; + +/* + Event data notifying the Cluster address of the cluster + which is reported as one of the Discovery engine event +*/ +typedef struct { + u8 addr[NAN_MAC_ADDR_LEN]; +} NanClusterEvent; + +/* + Discovery Engine Event Indication + The Discovery Engine can inform the Host when significant events occur + The data following the EventId is dependent upon the EventId type. + In other words, each new event defined will carry a different + structure of information back to the host. +*/ +typedef struct { + NanDiscEngEventType event_type; /* NAN Protocol Event Codes */ + union { + /* + MacAddressEvent which will have 6 byte mac address + of the Discovery engine. + */ + NanMacAddressEvent mac_addr; + /* + Cluster Event Data which will be obtained when the + device starts a new cluster or joins a cluster. + The event data will have 6 byte octet string of the + cluster started or joined. + */ + NanClusterEvent cluster; + } data; +} NanDiscEngEventInd; + +/* Cluster size TCA event*/ +typedef struct { + /* size of the cluster*/ + u32 cluster_size; +} NanTcaClusterEvent; + +/* + NAN TCA Indication + The Discovery Engine can inform the Host when significant events occur. + The data following the TcaId is dependent upon the TcaId type. + In other words, each new event defined will carry a different structure + of information back to the host. +*/ +typedef struct { + NanTcaType tca_type; + /* flag which defines if the configured Threshold has risen above the threshold */ + u8 rising_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which defines if the configured Threshold has fallen below the threshold */ + u8 falling_direction_evt_flag; /* 0 - no event, 1 - event */ + union { + /* + This event in obtained when the cluser size threshold + is crossed. Event will have the cluster size + */ + NanTcaClusterEvent cluster; + } data; +} NanTCAInd; + +/* + NAN Disabled Indication + The NanDisableInd message indicates to the upper layers that the Discovery + Engine has flushed all state and has been shutdown. When this message is received + the DE is guaranteed to have left the NAN cluster it was part of and will have terminated + any in progress Publishes or Subscribes. +*/ +typedef struct { + /* + Following reasons expected: + NAN_STATUS_SUCCESS + NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanDisabledInd; + +/* + NAN Beacon or SDF Payload Indication + The NanBeaconSdfPayloadInd message indicates to the upper layers that information + elements were received either in a Beacon or SDF which needs to be delivered + outside of a Publish/Subscribe Handle. +*/ +typedef struct { + /* The MAC address of the peer which sent the attributes.*/ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Optional attributes. Each optional attribute is associated with a flag + which specifies whether the attribute is valid or not + */ + /* NAN Receive Vendor Specific Attribute*/ + u8 is_vsa_received; + NanReceiveVendorSpecificAttribute vsa; + + /* NAN Beacon or SDF Payload Received*/ + u8 is_beacon_sdf_payload_received; + NanBeaconSdfPayloadReceive data; +} NanBeaconSdfPayloadInd; + +/* + Event Indication notifying the + transmit followup in progress +*/ +typedef struct { + transaction_id id; + /* + Following reason codes returned: + NAN_STATUS_SUCCESS + NAN_STATUS_NO_OTA_ACK + NAN_STATUS_PROTOCOL_FAILURE + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanTransmitFollowupInd; + +/* + Data request Initiator/Responder + app/service related info +*/ +typedef struct { + u16 ndp_app_info_len; + u8 ndp_app_info[NAN_DP_MAX_APP_INFO_LEN]; +} NanDataPathAppInfo; + +/* QoS configuration */ +typedef enum { NAN_DP_CONFIG_NO_QOS = 0, NAN_DP_CONFIG_QOS } NanDataPathQosCfg; + +/* Configuration params of Data request Initiator/Responder */ +typedef struct { + /* Status Indicating Security/No Security */ + NanDataPathSecurityCfgStatus security_cfg; + NanDataPathQosCfg qos_cfg; +} NanDataPathCfg; + +/* Nan Data Path Initiator requesting a data session */ +typedef struct { + /* + Unique Instance Id identifying the Responder's service. + This is same as publish_id notified on the subscribe side + in a publish/subscribe scenario + */ + u32 requestor_instance_id; /* Value 0 for no publish/subscribe */ + + /* Config flag for channel request */ + NanDataPathChannelCfg channel_request_type; + /* Channel frequency in MHz to start data-path */ + wifi_channel channel; + /* + Discovery MAC addr of the publisher/peer + */ + u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Interface name on which this NDP session is to be started. + This will be the same interface name provided during interface + create. + */ + char ndp_iface[IFNAMSIZ + 1]; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the Initiator */ + NanDataPathAppInfo app_info; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + /* length of service name */ + u32 service_name_len; + /* + UTF-8 encoded string identifying the service name. + The service name field is only used if a Nan discovery + is not associated with the NDP (out-of-band discovery). + */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathInitiatorRequest; + +/* + Data struct to initiate a data response on the responder side + for an indication received with a data request +*/ +typedef struct { + /* + Unique token Id generated on the initiator/responder + side used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* + Interface name on which this NDP session is to be started. + This will be the same interface name provided during interface + create. + */ + char ndp_iface[IFNAMSIZ + 1]; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the responder */ + NanDataPathAppInfo app_info; + /* Response Code indicating ACCEPT/REJECT/DEFER */ + NanDataPathResponseCode rsp_code; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + /* length of service name */ + u32 service_name_len; + /* + UTF-8 encoded string identifying the service name. + The service name field is only used if a Nan discovery + is not associated with the NDP (out-of-band discovery). + */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathIndicationResponse; + +/* NDP termination info */ +typedef struct { + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathEndRequest; + +/* + Event indication received on the + responder side when a Nan Data request or + NDP session is initiated on the Initiator side +*/ +typedef struct { + /* + Unique Instance Id corresponding to a service/session. + This is similar to the publish_id generated on the + publisher side + */ + u16 service_instance_id; + /* Discovery MAC addr of the peer/initiator */ + u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the initiator */ + NanDataPathAppInfo app_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathRequestInd; + +/* + Event indication of data confirm is received on both + initiator and responder side confirming a NDP session +*/ +typedef struct { + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* + NDI mac address of the peer + (required to derive target ipv6 address) + */ + u8 peer_ndi_mac_addr[NAN_MAC_ADDR_LEN]; + /* App/Service information of Initiator/Responder */ + NanDataPathAppInfo app_info; + /* Response code indicating ACCEPT/REJECT/DEFER */ + NanDataPathResponseCode rsp_code; + /* + Reason code indicating the cause for REJECT. + NAN_STATUS_SUCCESS and NAN_STATUS_PROTOCOL_FAILURE are + expected reason codes. + */ + NanStatusType reason_code; + /* Number of channels for which info is indicated */ + u32 num_channels; + /* + Data indicating the Channel list and BW of the channel. + */ + NanChannelInfo channel_info[NAN_MAX_CHANNEL_INFO_SUPPORTED]; +} NanDataPathConfirmInd; + +/* + Event indication of schedule update is received on both + initiator and responder when a schedule change occurs +*/ +typedef struct { + /* + NMI mac address + */ + u8 peer_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Reason code indicating the cause of schedule update. + BIT_0 NSS Update + BIT_1 Channel list update + */ + u32 schedule_update_reason_code; + /* Number of channels for which info is indicated */ + u32 num_channels; + /* + Data indicating the Channel list and BW of the channel. + */ + NanChannelInfo channel_info[NAN_MAX_CHANNEL_INFO_SUPPORTED]; + /* Number of NDP instance Ids */ + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathScheduleUpdateInd; + +/* + Event indication received on the + initiator/responder side terminating + a NDP session +*/ +typedef struct { + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathEndInd; + +/* + Event indicating Range Request received on the + Published side. +*/ +typedef struct { + u16 publish_id; /* id is existing publish */ + /* Range Requestor's MAC address */ + u8 range_req_intf_addr[NAN_MAC_ADDR_LEN]; +} NanRangeRequestInd; + +/* + Event indicating Range report on the + Published side. +*/ +typedef struct { + u16 publish_id; /* id is existing publish */ + /* Range Requestor's MAC address */ + u8 range_req_intf_addr[NAN_MAC_ADDR_LEN]; + /* + Distance to the NAN device with the MAC address indicated + with ranged mac address. + */ + u32 range_measurement_mm; +} NanRangeReportInd; + +/* Response and Event Callbacks */ +typedef struct { + /* NotifyResponse invoked to notify the status of the Request */ + void (*NotifyResponse)(transaction_id id, NanResponseMsg* rsp_data); + /* Callbacks for various Events */ + void (*EventPublishReplied)(NanPublishRepliedInd* event); + void (*EventPublishTerminated)(NanPublishTerminatedInd* event); + void (*EventMatch)(NanMatchInd* event); + void (*EventMatchExpired)(NanMatchExpiredInd* event); + void (*EventSubscribeTerminated)(NanSubscribeTerminatedInd* event); + void (*EventFollowup)(NanFollowupInd* event); + void (*EventDiscEngEvent)(NanDiscEngEventInd* event); + void (*EventDisabled)(NanDisabledInd* event); + void (*EventTca)(NanTCAInd* event); + void (*EventBeaconSdfPayload)(NanBeaconSdfPayloadInd* event); + void (*EventDataRequest)(NanDataPathRequestInd* event); + void (*EventDataConfirm)(NanDataPathConfirmInd* event); + void (*EventDataEnd)(NanDataPathEndInd* event); + void (*EventTransmitFollowup)(NanTransmitFollowupInd* event); + void (*EventRangeRequest)(NanRangeRequestInd* event); + void (*EventRangeReport)(NanRangeReportInd* event); + void (*EventScheduleUpdate)(NanDataPathScheduleUpdateInd* event); +} NanCallbackHandler; + +/**@brief nan_enable_request + * Enable NAN functionality + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanEnableRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_ALREADY_ENABLED + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NAN_NOT_ALLOWED + */ +wifi_error nan_enable_request(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + +/**@brief nan_disbale_request + * Disable NAN functionality. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDisableRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_PROTOCOL_FAILURE + * + */ +wifi_error nan_disable_request(transaction_id id, wifi_interface_handle iface); + +/**@brief nan_publish_request + * Publish request to advertize a service + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanPublishRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NO_RESOURCE_AVAILABLE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + */ +wifi_error nan_publish_request(transaction_id id, wifi_interface_handle iface, + NanPublishRequest* msg); + +/**@brief nan_publish_cancel_request + * Cancel previous publish request + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanPublishCancelRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_publish_cancel_request(transaction_id id, wifi_interface_handle iface, + NanPublishCancelRequest* msg); + +/**@brief nan_subscribe_request + * Subscribe request to search for a service + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanSubscribeRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_NO_SPACE_AVAILABLE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + */ +wifi_error nan_subscribe_request(transaction_id id, wifi_interface_handle iface, + NanSubscribeRequest* msg); + +/**@brief nan_subscribe_cancel_request + * Cancel previous subscribe requests. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanSubscribeRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_subscribe_cancel_request(transaction_id id, wifi_interface_handle iface, + NanSubscribeCancelRequest* msg); + +/**@brief nan_transmit_followup_request + * NAN transmit follow up request + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanTransmitFollowupRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID + * NAN_STATUS_FOLLOWUP_QUEUE_FULL + * @return Asynchronous TransmitFollowupInd CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NO_OTA_ACK + */ +wifi_error nan_transmit_followup_request(transaction_id id, wifi_interface_handle iface, + NanTransmitFollowupRequest* msg); + +/**@brief nan_stats_request + * Request NAN statistics from Discovery Engine. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_INVALID_PARAM + */ +wifi_error nan_stats_request(transaction_id id, wifi_interface_handle iface, NanStatsRequest* msg); + +/**@brief nan_config_request + * NAN configuration request. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanConfigRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_config_request(transaction_id id, wifi_interface_handle iface, + NanConfigRequest* msg); + +/**@brief nan_tca_request + * Configure the various Threshold crossing alerts + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_tca_request(transaction_id id, wifi_interface_handle iface, NanTCARequest* msg); + +/**@brief nan_beacon_sdf_payload_request + * Set NAN Beacon or sdf payload to discovery engine. + * This instructs the Discovery Engine to begin publishing the + * received payload in any Beacon or Service Discovery Frame transmitted + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_beacon_sdf_payload_request(transaction_id id, wifi_interface_handle iface, + NanBeaconSdfPayloadRequest* msg); + +/* Register NAN callbacks. */ +wifi_error nan_register_handler(wifi_interface_handle iface, NanCallbackHandler handlers); + +/* Get NAN HAL version. */ +wifi_error nan_get_version(wifi_handle handle, NanVersion* version); + +/**@brief nan_get_capabilities + * Get NAN Capabilities + * + * @param transaction_id: + * @param wifi_interface_handle: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + */ +/* Get NAN capabilities. */ +wifi_error nan_get_capabilities(transaction_id id, wifi_interface_handle iface); + +/* ========== Nan Data Path APIs ================ */ +/**@brief nan_data_interface_create + * Create NAN Data Interface. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param iface_name: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_data_interface_create(transaction_id id, wifi_interface_handle iface, + char* iface_name); + +/**@brief nan_data_interface_delete + * Delete NAN Data Interface. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param iface_name: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_data_interface_delete(transaction_id id, wifi_interface_handle iface, + char* iface_name); + +/**@brief nan_data_request_initiator + * Initiate a NAN Data Path session. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathInitiatorRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID + */ +wifi_error nan_data_request_initiator(transaction_id id, wifi_interface_handle iface, + NanDataPathInitiatorRequest* msg); + +/**@brief nan_data_indication_response + * Response to a data indication received + * corresponding to a NDP session. An indication + * is received with a data request and the responder + * will send a data response + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathIndicationResponse: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_NDP_ID + */ +wifi_error nan_data_indication_response(transaction_id id, wifi_interface_handle iface, + NanDataPathIndicationResponse* msg); + +/**@brief nan_data_end + * NDL termination request: from either Initiator/Responder + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathEndRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_NDP_ID + */ +wifi_error nan_data_end(transaction_id id, wifi_interface_handle iface, NanDataPathEndRequest* msg); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NAN_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h new file mode 100644 index 0000000..0c69e39 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h @@ -0,0 +1,30 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_OFFLOAD_H +#define __WIFI_HAL_OFFLOAD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define ETHER_ADDR_LEN 6 // Ethernet frame address length +#define N_AVAIL_ID 3 // available mkeep_alive IDs from 1 to 3 +#define MKEEP_ALIVE_IP_PKT_MAX 256 // max size of IP packet for keep alive + +/** + * Send specified keep alive packet periodically. + */ +wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface, + u16 ether_type, u8* ip_packet, u16 ip_packet_len, + u8* src_mac_addr, u8* dst_mac_addr, u32 period_msec); + +/** + * Stop sending keep alive packet. + */ +wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_OFFLOAD_H */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h new file mode 100644 index 0000000..994bb18 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2020 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_HAL_TWT_H__ +#define __WIFI_HAL_TWT_H__ + +#include "wifi_hal.h" + +typedef struct { + u8 requester_supported; // 0 for not supporting requester + u8 responder_supported; // 0 for not supporting responder + u8 broadcast_twt_supported; // 0 for not supporting broadcast TWT + u8 flexibile_twt_supported; // 0 for not supporting flexible TWT +} TwtCapability; + +typedef struct { + TwtCapability device_capability; + TwtCapability peer_capability; +} TwtCapabilitySet; + +// For all optional fields below, if no value specify -1 +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT + u8 trigger_type; // 0 for non-triggered TWT, 1 for triggered TWT + s32 wake_dur_us; // Proposed wake duration in us + s32 wake_int_us; // Average wake interval in us + s32 wake_int_min_us; // Min wake interval in us. Optional. + s32 wake_int_max_us; // Max wake interval in us. Optional. + s32 wake_dur_min_us; // Min wake duration in us. Optional. + s32 wake_dur_max_us; // Max wake duration in us. Optional. + s32 avg_pkt_size; // Average bytes of each packet to send in each wake + // duration. Optional. + s32 avg_pkt_num; // Average number of packets to send in each wake + // duration. Optional. + s32 wake_time_off_us; // First wake duration time offset in us. Optional. +} TwtSetupRequest; + +typedef enum { + TWT_SETUP_SUCCESS = 0, // TWT setup is accepted. + TWT_SETUP_REJECT = 1, // TWT setup is rejected by AP. + TWT_SETUP_TIMEOUT = 2, // TWT setup response from AP times out. + TWT_SETUP_IE = 3, // AP sent TWT Setup IE parsing failure. + TWT_SETUP_PARAMS = 4, // AP sent TWT Setup IE Parameters invalid. + TWT_SETUP_ERROR = 255, // Generic error +} TwtSetupReasonCode; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 status; // 0 for success, non-zero for failure + TwtSetupReasonCode reason_code; + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT + u8 trigger_type; // 0 for non-triggered TWT, 1 for triggered TWT + s32 wake_dur_us; // Proposed wake duration in us + s32 wake_int_us; // Average wake interval in us + s32 wake_time_off_us; // First wake duration time offset in us. +} TwtSetupResponse; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setp request, 1 for all TWT + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT +} TwtTeardownRequest; + +typedef enum { + TWT_TD_RC_HOST = 0, // Teardown triggered by Host + TWT_TD_RC_PEER = 1, // Peer initiated teardown + TWT_TD_RC_MCHAN = 2, // Teardown due to MCHAN Active + TWT_TD_RC_MCNX = 3, // Teardown due to MultiConnection + TWT_TD_RC_CSA = 4, // Teardown due to CSA + TWT_TD_RC_BTCX = 5, // Teardown due to BT Coex + TWT_TD_RC_SETUP_FAIL = 6, // Setup fails midway. Teardown all connections + TWT_TD_RC_SCHED = 7, // Teardown by TWT Scheduler + TWT_TD_RC_ERROR = 255, // Generic error cases +} TwtTeardownReason; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setp request, 1 for all TWT + u8 status; // 0 for success, non-zero for failure + TwtTeardownReason reason; +} TwtTeardownCompletion; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setup request, 1 for all TWT + s32 resume_time_us; // If -1, TWT is suspended for indefinite time. + // Otherwise, TWT is suspended for resume_time_us +} TwtInfoFrameRequest; + +typedef enum { + TWT_INFO_RC_HOST = 0, // Host initiated TWT Info frame */ + TWT_INFO_RC_PEER = 1, // Peer initiated TWT Info frame + TWT_INFO_RC_ERROR = 2, // Generic error conditions */ +} TwtInfoFrameReason; + +// TWT Info frame triggered externally. +// Device should not send TwtInfoFrameReceived to Host for internally +// triggered TWT Info frame during SCAN, MCHAN operations. +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setup request, 1 for all TWT + u8 status; // 0 for success, non-zero for failure + TwtInfoFrameReason reason; + u8 twt_resumed; // 1 - TWT resumed, 0 - TWT suspended +} TwtInfoFrameReceived; + +typedef struct { + u8 config_id; + u32 avg_pkt_num_tx; // Average number of Tx packets in each wake duration. + u32 avg_pkt_num_rx; // Average number of Rx packets in each wake duration. + u32 avg_tx_pkt_size; // Average bytes per Rx packet in each wake duration. + u32 avg_rx_pkt_size; // Average bytes per Rx packet in each wake duration. + u32 avg_eosp_dur_us; // Average duration of early terminated SP + u32 eosp_count; // Count of early terminations + u32 num_sp; // Count of service period (SP), also known as wake duration. +} TwtStats; + +// Asynchronous notification from the device. +// For example, TWT was torn down by the device and later when the device is +// ready, it can send this async notification. +// This can be expandable in future. +typedef enum { + TWT_NOTIF_ALLOW_TWT = 1, // Device ready to process TWT Setup request +} TwtNotification; + +typedef struct { + TwtNotification notification; +} TwtDeviceNotify; + +// Callbacks for various TWT responses and events +typedef struct { + // Callback for TWT setup response + void (*EventTwtSetupResponse)(TwtSetupResponse* event); + // Callback for TWT teardown completion + void (*EventTwtTeardownCompletion)(TwtTeardownCompletion* event); + // Callback for TWT info frame received event + void (*EventTwtInfoFrameReceived)(TwtInfoFrameReceived* event); + // Callback for TWT notification from the device + void (*EventTwtDeviceNotify)(TwtDeviceNotify* event); +} TwtCallbackHandler; + +#endif /* __WIFI_HAL_TWT_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h new file mode 100644 index 0000000..aab0ae5 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h @@ -0,0 +1,122 @@ +/* + * 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 <set> + +#include <hidl/HidlSupport.h> +#include <hidl/HidlTransportSupport.h> + +namespace { +// Type of callback invoked by the death handler. +using on_death_cb_function = std::function<void(uint64_t)>; + +// Private class used to keep track of death of individual +// callbacks stored in HidlCallbackHandler. +template <typename CallbackType> +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<android::hidl::base::V1_0::IBase>& /* 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_6 { +namespace implementation { +namespace hidl_callback_util { +template <typename CallbackType> +// 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<CallbackType>( + std::bind(&HidlCallbackHandler::onObjectDeath, this, std::placeholders::_1))) {} + ~HidlCallbackHandler() = default; + + bool addCallback(const sp<CallbackType>& 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<uint64_t>(cb.get()); + for (const auto& s : cb_set_) { + if (interfacesEqual(cb, s)) { + LOG(ERROR) << "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<android::sp<CallbackType>>& getCallbacks() { return cb_set_; } + + // Death notification for callbacks. + void onObjectDeath(uint64_t cookie) { + CallbackType* cb = reinterpret_cast<CallbackType*>(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<CallbackType>& cb : cb_set_) { + if (!cb->unlinkToDeath(death_handler_)) { + LOG(ERROR) << "Failed to deregister death notification"; + } + } + cb_set_.clear(); + } + + private: + std::set<sp<CallbackType>> cb_set_; + sp<HidlDeathHandler<CallbackType>> death_handler_; + + DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); +}; + +} // namespace hidl_callback_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_CALLBACK_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h new file mode 100644 index 0000000..a0efac2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h @@ -0,0 +1,118 @@ +/* + * 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_6 { +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 <typename ObjT, typename WorkFuncT, typename... Args> +Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&)>& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(std::forward<Args>(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return only an instance of WifiStatus. +// This version passes the global lock acquired to the body of the method. +// Note: Only used by IWifi::stop() currently. +template <typename ObjT, typename WorkFuncT, typename... Args> +Return<void> validateAndCallWithLock(ObjT* obj, WifiStatusCode status_code_if_invalid, + WorkFuncT&& work, + const std::function<void(const WifiStatus&)>& hidl_cb, + Args&&... args) { + auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(&lock, std::forward<Args>(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 <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args> +Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_pair = (obj->*work)(std::forward<Args>(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<ReturnT>::type()); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and 2 return +// values. +template <typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2, typename... Args> +Return<void> validateAndCall( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb, Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_tuple = (obj->*work)(std::forward<Args>(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<ReturnT1>::type(), + typename std::remove_reference<ReturnT2>::type()); + } + return Void(); +} + +} // namespace hidl_return_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_RETURN_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp new file mode 100644 index 0000000..2112b26 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp @@ -0,0 +1,3007 @@ +/* + * 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 <android-base/logging.h> +#include <utils/SystemClock.h> + +#include "hidl_struct_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_struct_util { + +using V1_6::NanConfigRequestSupplemental; + +WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(legacy_hal::wifi_channel_width type); + +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 {}; +} + +V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(uint64_t feature) { + using HidlChipCaps = V1_5::IWifiChip::ChipCapabilityMask; + switch (feature) { + case WIFI_FEATURE_SET_TX_POWER_LIMIT: + return HidlChipCaps::SET_TX_POWER_LIMIT; + case WIFI_FEATURE_USE_BODY_HEAD_SAR: + return HidlChipCaps::USE_BODY_HEAD_SAR; + case WIFI_FEATURE_D2D_RTT: + return HidlChipCaps::D2D_RTT; + case WIFI_FEATURE_D2AP_RTT: + return HidlChipCaps::D2AP_RTT; + case WIFI_FEATURE_INFRA_60G: + return HidlChipCaps::WIGIG; + case WIFI_FEATURE_SET_LATENCY_MODE: + return HidlChipCaps::SET_LATENCY_MODE; + case WIFI_FEATURE_P2P_RAND_MAC: + return HidlChipCaps::P2P_RAND_MAC; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask convertLegacyFeatureToHidlStaIfaceCapability( + uint64_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(uint64_t legacy_feature_set, + 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); + } + } + std::vector<uint64_t> features = {WIFI_FEATURE_SET_TX_POWER_LIMIT, + WIFI_FEATURE_USE_BODY_HEAD_SAR, + WIFI_FEATURE_D2D_RTT, + WIFI_FEATURE_D2AP_RTT, + WIFI_FEATURE_INFRA_60G, + WIFI_FEATURE_SET_LATENCY_MODE, + WIFI_FEATURE_P2P_RAND_MAC}; + for (const auto feature : features) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlChipCapability(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<const char*>(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<std::underlying_type<WifiDebugRingBufferFlags>::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_hal::wifi_ring_buffer_status>& legacy_status_vec, + std::vector<WifiDebugRingBufferStatus>* 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; +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + }; + CHECK(false); +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + // Those are the supported scenarios for V1_2 + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; + }; + CHECK(false); +} + +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + V1_3::IWifiChip::LatencyMode hidl_latency_mode) { + switch (hidl_latency_mode) { + case V1_3::IWifiChip::LatencyMode::NORMAL: + return legacy_hal::WIFI_LATENCY_MODE_NORMAL; + case V1_3::IWifiChip::LatencyMode::LOW: + return legacy_hal::WIFI_LATENCY_MODE_LOW; + } + CHECK(false); +} + +bool convertLegacyWifiMacInfoToHidl( + const legacy_hal::WifiMacInfo& legacy_mac_info, + V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { + if (!hidl_radio_mode_info) { + return false; + } + *hidl_radio_mode_info = {}; + + hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id; + // Convert from bitmask of bands in the legacy HAL to enum value in + // the HIDL interface. + if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ; + } else { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_UNSPECIFIED; + } + std::vector<V1_2::IWifiChipEventCallback::IfaceInfo> iface_info_vec; + for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) { + V1_2::IWifiChipEventCallback::IfaceInfo iface_info; + iface_info.name = legacy_iface_info.name; + iface_info.channel = legacy_iface_info.channel; + iface_info_vec.push_back(iface_info); + } + hidl_radio_mode_info->ifaceInfos = iface_info_vec; + return true; +} + +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) { + switch (hidl_band) { + case V1_5::WifiBand::BAND_24GHZ: + return legacy_hal::WLAN_MAC_2_4_BAND; + case V1_5::WifiBand::BAND_5GHZ: + case V1_5::WifiBand::BAND_5GHZ_DFS: + case V1_5::WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WLAN_MAC_5_0_BAND; + case V1_5::WifiBand::BAND_24GHZ_5GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND); + case V1_5::WifiBand::BAND_6GHZ: + return legacy_hal::WLAN_MAC_6_0_BAND; + case V1_5::WifiBand::BAND_5GHZ_6GHZ: + return (legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_60GHZ: + return legacy_hal::WLAN_MAC_60_0_BAND; + default: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND); + } +} + +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band) { + switch (band) { + case legacy_hal::WLAN_MAC_2_4_BAND: + return V1_5::WifiBand::BAND_24GHZ; + case legacy_hal::WLAN_MAC_5_0_BAND: + return V1_5::WifiBand::BAND_5GHZ; + case legacy_hal::WLAN_MAC_6_0_BAND: + return V1_5::WifiBand::BAND_6GHZ; + case legacy_hal::WLAN_MAC_60_0_BAND: + return V1_5::WifiBand::BAND_60GHZ; + default: + return V1_5::WifiBand::BAND_UNSPECIFIED; + } +} + +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) { + uint32_t legacy_iface_mask = 0; + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_NAN) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_TDLS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_MESH) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_IBSS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS); + } + return legacy_iface_mask; +} + +uint32_t convertLegacyWifiInterfaceModeToHidl(uint32_t legacy_iface_mask) { + uint32_t hidl_iface_mask = 0; + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_STA; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_NAN; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_TDLS; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_MESH; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_IBSS; + } + return hidl_iface_mask; +} + +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask) { + uint32_t legacy_filter_mask = 0; + if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) { + legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; + } + if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CONCURRENCY) { + legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; + } + if (hidl_filter_mask & V1_6::IWifiChip::UsableChannelFilter::NAN_INSTANT_MODE) { + legacy_filter_mask |= WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE; + } + return legacy_filter_mask; +} + +bool convertLegacyWifiUsableChannelToHidl( + const legacy_hal::wifi_usable_channel& legacy_usable_channel, + V1_6::WifiUsableChannel* hidl_usable_channel) { + if (!hidl_usable_channel) { + return false; + } + *hidl_usable_channel = {}; + hidl_usable_channel->channel = legacy_usable_channel.freq; + hidl_usable_channel->channelBandwidth = + convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width); + hidl_usable_channel->ifaceModeMask = + convertLegacyWifiInterfaceModeToHidl(legacy_usable_channel.iface_mode_mask); + + return true; +} + +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels, + std::vector<V1_6::WifiUsableChannel>* hidl_usable_channels) { + if (!hidl_usable_channels) { + return false; + } + *hidl_usable_channels = {}; + for (const auto& legacy_usable_channel : legacy_usable_channels) { + V1_6::WifiUsableChannel hidl_usable_channel; + if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel, &hidl_usable_channel)) { + return false; + } + hidl_usable_channels->push_back(hidl_usable_channel); + } + return true; +} + +bool convertLegacyWifiMacInfosToHidl( + const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos, + std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) { + if (!hidl_radio_mode_infos) { + return false; + } + *hidl_radio_mode_infos = {}; + + for (const auto& legacy_mac_info : legacy_mac_infos) { + V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; + if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) { + return false; + } + hidl_radio_mode_infos->push_back(hidl_radio_mode_info); + } + return true; +} + +bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + 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(V1_0::WifiBand band) { + switch (band) { + case V1_0::WifiBand::BAND_UNSPECIFIED: + return legacy_hal::WIFI_BAND_UNSPECIFIED; + case V1_0::WifiBand::BAND_24GHZ: + return legacy_hal::WIFI_BAND_BG; + case V1_0::WifiBand::BAND_5GHZ: + return legacy_hal::WIFI_BAND_A; + case V1_0::WifiBand::BAND_5GHZ_DFS: + return legacy_hal::WIFI_BAND_A_DFS; + case V1_0::WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_A_WITH_DFS; + case V1_0::WifiBand::BAND_24GHZ_5GHZ: + return legacy_hal::WIFI_BAND_ABG; + case V1_0::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<std::underlying_type<HidlFlag>::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<uint8_t>(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<WifiInformationElement>* 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<const wifi_ie*>(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<uint8_t>( + 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<WifiInformationElement> ies; + if (!convertLegacyIeBlobToHidl(reinterpret_cast<const uint8_t*>(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<std::underlying_type<StaScanDataFlagMask>::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<StaScanResult> 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_hal::wifi_cached_scan_results>& legacy_cached_scan_results, + std::vector<StaScanData>* 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<const uint8_t*>(legacy_frame.frame_content.ethernet_ii_bytes); + hidl_frame->frameContent = + std::vector<uint8_t>(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_hal::wifi_tx_report>& legacy_fates, + std::vector<WifiDebugTxPacketFateReport>* 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_hal::wifi_rx_report>& legacy_fates, + std::vector<WifiDebugRxPacketFateReport>* 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 convertLegacyLinkLayerRadioStatsToHidl( + const legacy_hal::LinkLayerRadioStats& legacy_radio_stat, + V1_6::StaLinkLayerRadioStats* hidl_radio_stat) { + if (!hidl_radio_stat) { + return false; + } + *hidl_radio_stat = {}; + + hidl_radio_stat->radioId = legacy_radio_stat.stats.radio; + hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time; + hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time; + hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time; + hidl_radio_stat->V1_0.onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan; + hidl_radio_stat->V1_0.txTimeInMsPerLevel = legacy_radio_stat.tx_time_per_levels; + hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd; + hidl_radio_stat->onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan; + hidl_radio_stat->onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan; + hidl_radio_stat->onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan; + hidl_radio_stat->onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20; + + std::vector<V1_6::WifiChannelStats> hidl_channel_stats; + + for (const auto& channel_stat : legacy_radio_stat.channel_stats) { + V1_6::WifiChannelStats hidl_channel_stat; + hidl_channel_stat.onTimeInMs = channel_stat.on_time; + hidl_channel_stat.ccaBusyTimeInMs = channel_stat.cca_busy_time; + /* + * TODO once b/119142899 is fixed, + * replace below code with convertLegacyWifiChannelInfoToHidl() + */ + hidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20; + hidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq; + hidl_channel_stat.channel.centerFreq0 = channel_stat.channel.center_freq0; + hidl_channel_stat.channel.centerFreq1 = channel_stat.channel.center_freq1; + hidl_channel_stats.push_back(hidl_channel_stat); + } + + hidl_radio_stat->channelStats = hidl_channel_stats; + + return true; +} + +bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats, + V1_6::StaLinkLayerStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + // iface legacy_stats conversion. + hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx; + hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + hidl_stats->iface.V1_0.wmeBePktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + hidl_stats->iface.V1_0.wmeBePktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg; + hidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples; + hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + hidl_stats->iface.V1_0.wmeBkPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg; + hidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples; + hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + hidl_stats->iface.V1_0.wmeViPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + hidl_stats->iface.V1_0.wmeViPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg; + hidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples; + hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + hidl_stats->iface.V1_0.wmeVoPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg; + hidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples; + hidl_stats->iface.timeSliceDutyCycleInPercent = + legacy_stats.iface.info.time_slicing_duty_cycle_percent; + // peer info legacy_stats conversion. + std::vector<V1_6::StaPeerInfo> hidl_peers_info_stats; + for (const auto& legacy_peer_info_stats : legacy_stats.peers) { + V1_6::StaPeerInfo hidl_peer_info_stats; + if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats, &hidl_peer_info_stats)) { + return false; + } + hidl_peers_info_stats.push_back(hidl_peer_info_stats); + } + hidl_stats->iface.peers = hidl_peers_info_stats; + // radio legacy_stats conversion. + std::vector<V1_6::StaLinkLayerRadioStats> hidl_radios_stats; + for (const auto& legacy_radio_stats : legacy_stats.radios) { + V1_6::StaLinkLayerRadioStats hidl_radio_stats; + if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, &hidl_radio_stats)) { + return false; + } + 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 convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + V1_6::StaPeerInfo* hidl_peer_info_stats) { + if (!hidl_peer_info_stats) { + return false; + } + *hidl_peer_info_stats = {}; + hidl_peer_info_stats->staCount = legacy_peer_info_stats.peer_info.bssload.sta_count; + hidl_peer_info_stats->chanUtil = legacy_peer_info_stats.peer_info.bssload.chan_util; + + std::vector<V1_6::StaRateStat> hidlRateStats; + for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) { + V1_6::StaRateStat rateStat; + if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate, &rateStat.rateInfo)) { + return false; + } + rateStat.txMpdu = legacy_rate_stats.tx_mpdu; + rateStat.rxMpdu = legacy_rate_stats.rx_mpdu; + rateStat.mpduLost = legacy_rate_stats.mpdu_lost; + rateStat.retries = legacy_rate_stats.retries; + hidlRateStats.push_back(rateStat); + } + hidl_peer_info_stats->rateStats = hidlRateStats; + 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 V1_4::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() != 3) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "bandSpecificConfig.size() != 3"; + 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]; + + /* TODO: b/145609058 + * Missing updates needed to legacy_hal::NanEnableRequest and conversion to + * it for 6GHz band */ + + return true; +} + +bool convertHidlNanEnableRequest_1_6ToLegacy(const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanEnableRequest_1_6ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging; + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode; + legacy_request->config_instant_mode_channel = 1; + legacy_request->instant_mode_channel = hidl_request2.instantModeChannel; + + return true; +} + +bool convertHidlNanConfigRequest_1_6ToLegacy(const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanConfigRequest_1_6ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging; + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode; + legacy_request->config_instant_mode_channel = 1; + legacy_request->instant_mode_channel = hidl_request2.instantModeChannel; + + return true; +} + +bool convertHidlNanPublishRequestToLegacy(const V1_6::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; + + legacy_request->scid_len = hidl_request.baseConfigs.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.baseConfigs.securityConfig.scid.data(), + legacy_request->scid_len); + + 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_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10; + 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 V1_0::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_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10; + 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 V1_4::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; + /* TODO: b/145609058 + * Missing updates needed to legacy_hal::NanConfigRequest and conversion to + * it for 6GHz band */ + + return true; +} + +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const V1_0::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; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + 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 convertHidlNanDataPathInitiatorRequest_1_6ToLegacy( + const V1_6::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "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; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + 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) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "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) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "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) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "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) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + legacy_request->scid_len = hidl_request.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_len); + + return true; +} + +bool convertHidlNanDataPathIndicationResponseToLegacy( + const V1_0::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; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + 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 convertHidlNanDataPathIndicationResponse_1_6ToLegacy( + const V1_6::NanRespondToDataPathIndicationRequest& hidl_request, + legacy_hal::NanDataPathIndicationResponse* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "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; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + 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) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "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) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "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) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "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) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + legacy_request->scid_len = hidl_request.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_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, + V1_6::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; + hidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported; + + return true; +} + +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + V1_6::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<uint8_t, 6>(legacy_ind.addr); + hidl_ind->serviceSpecificInfo = std::vector<uint8_t>( + legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>( + legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len); + hidl_ind->matchFilter = + std::vector<uint8_t>(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 = (V1_6::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->rangingMeasurementInMm = legacy_ind.range_info.range_measurement_mm; + hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type; + hidl_ind->scid = std::vector<uint8_t>(legacy_ind.scid, legacy_ind.scid + legacy_ind.scid_len); + 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<uint8_t, 6>(legacy_ind.addr); + hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1; + hidl_ind->serviceSpecificInfo = std::vector<uint8_t>( + legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>( + 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<uint8_t, 6>(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<uint8_t>( + 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 convertLegacyNdpChannelInfoToHidl(const legacy_hal::NanChannelInfo& legacy_struct, + V1_6::NanDataPathChannelInfo* hidl_struct) { + if (!hidl_struct) { + LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null"; + return false; + } + *hidl_struct = {}; + + hidl_struct->channelFreq = legacy_struct.channel; + hidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToHidl( + (legacy_hal::wifi_channel_width)legacy_struct.bandwidth); + hidl_struct->numSpatialStreams = legacy_struct.nss; + + return true; +} + +bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind, + V1_6::NanDataPathConfirmInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->V1_0.dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT; + hidl_ind->V1_0.peerNdiMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr); + hidl_ind->V1_0.appInfo = std::vector<uint8_t>( + legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len); + hidl_ind->V1_0.status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code); + hidl_ind->V1_0.status.description = ""; // TODO: b/34059183 + + std::vector<V1_6::NanDataPathChannelInfo> channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_6::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + + return true; +} + +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_6::NanDataPathScheduleUpdateInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: " + "hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->peerDiscoveryAddress = hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr); + std::vector<V1_6::NanDataPathChannelInfo> channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_6::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + std::vector<uint32_t> ndpInstanceIds; + for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) { + ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]); + } + hidl_ind->ndpInstanceIds = ndpInstanceIds; + + 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 V1_6::WifiChannelWidthInMhz::WIDTH_320: + return legacy_hal::WIFI_CHAN_WIDTH_320; + case WifiChannelWidthInMhz::WIDTH_INVALID: + return legacy_hal::WIFI_CHAN_WIDTH_INVALID; + }; + CHECK(false); +} + +V1_6::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_320: + return V1_6::WifiChannelWidthInMhz::WIDTH_320; + default: + return WifiChannelWidthInMhz::WIDTH_INVALID; + }; +} + +legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(V1_6::RttPreamble type) { + switch (type) { + case V1_6::RttPreamble::LEGACY: + return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY; + case V1_6::RttPreamble::HT: + return legacy_hal::WIFI_RTT_PREAMBLE_HT; + case V1_6::RttPreamble::VHT: + return legacy_hal::WIFI_RTT_PREAMBLE_VHT; + case V1_6::RttPreamble::HE: + return legacy_hal::WIFI_RTT_PREAMBLE_HE; + case V1_6::RttPreamble::EHT: + return legacy_hal::WIFI_RTT_PREAMBLE_EHT; + }; + CHECK(false); +} + +V1_6::RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) { + switch (type) { + case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY: + return V1_6::RttPreamble::LEGACY; + case legacy_hal::WIFI_RTT_PREAMBLE_HT: + return V1_6::RttPreamble::HT; + case legacy_hal::WIFI_RTT_PREAMBLE_VHT: + return V1_6::RttPreamble::VHT; + case legacy_hal::WIFI_RTT_PREAMBLE_HE: + return V1_6::RttPreamble::HE; + case legacy_hal::WIFI_RTT_PREAMBLE_EHT: + return V1_6::RttPreamble::EHT; + }; + 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; + case RttBw::BW_320MHZ: + return legacy_hal::WIFI_RTT_BW_320; + }; + 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; + case legacy_hal::WIFI_RTT_BW_320: + return RttBw::BW_320MHZ; + }; + 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); +} + +V1_6::WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { + switch (preamble) { + case 0: + return V1_6::WifiRatePreamble::OFDM; + case 1: + return V1_6::WifiRatePreamble::CCK; + case 2: + return V1_6::WifiRatePreamble::HT; + case 3: + return V1_6::WifiRatePreamble::VHT; + case 4: + return V1_6::WifiRatePreamble::HE; + case 5: + return V1_6::WifiRatePreamble::EHT; + default: + return V1_6::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; + case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + }; + 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 V1_6::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<V1_6::RttConfig>& hidl_configs, + std::vector<legacy_hal::wifi_rtt_config>* 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 V1_6::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, + V1_6::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, + V1_6::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, legacy_hal::WIFI_RTT_PREAMBLE_HE, + legacy_hal::WIFI_RTT_PREAMBLE_EHT}) { + if (legacy_capabilities.preamble_support & flag) { + hidl_capabilities->preambleSupport |= + static_cast<std::underlying_type<V1_6::RttPreamble>::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, + legacy_hal::WIFI_RTT_BW_320}) { + if (legacy_capabilities.bw_support & flag) { + hidl_capabilities->bwSupport |= + static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToHidl(flag)); + } + } + hidl_capabilities->mcVersion = legacy_capabilities.mc_version; + return true; +} + +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + V1_6::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_hal::wifi_channel_width>(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, + V1_6::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<const legacy_hal::wifi_rtt_result*>& legacy_results, + std::vector<V1_6::RttResult>* hidl_results) { + if (!hidl_results) { + return false; + } + *hidl_results = {}; + for (const auto legacy_result : legacy_results) { + V1_6::RttResult hidl_result; + if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) { + return false; + } + hidl_results->push_back(hidl_result); + } + return true; +} + +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type) { + switch (hidl_interface_type) { + case IfaceType::STA: + return legacy_hal::WIFI_INTERFACE_TYPE_STA; + case IfaceType::AP: + return legacy_hal::WIFI_INTERFACE_TYPE_AP; + case IfaceType::P2P: + return legacy_hal::WIFI_INTERFACE_TYPE_P2P; + case IfaceType::NAN: + return legacy_hal::WIFI_INTERFACE_TYPE_NAN; + } + CHECK(false); +} + +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + V1_5::IWifiChip::MultiStaUseCase use_case) { + switch (use_case) { + case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY: + return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; + case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED: + return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; + } + CHECK(false); +} + +bool convertHidlCoexUnsafeChannelToLegacy( + const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) { + if (!legacy_unsafe_channel) { + return false; + } + *legacy_unsafe_channel = {}; + switch (hidl_unsafe_channel.band) { + case V1_5::WifiBand::BAND_24GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND; + break; + case V1_5::WifiBand::BAND_5GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND; + break; + default: + return false; + }; + legacy_unsafe_channel->channel = hidl_unsafe_channel.channel; + legacy_unsafe_channel->power_cap_dbm = hidl_unsafe_channel.powerCapDbm; + return true; +} + +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels, + std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) { + if (!legacy_unsafe_channels) { + return false; + } + *legacy_unsafe_channels = {}; + for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) { + legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel; + if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(hidl_unsafe_channel, + &legacy_unsafe_channel)) { + return false; + } + legacy_unsafe_channels->push_back(legacy_unsafe_channel); + } + return true; +} + +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg) { + switch (antenna_cfg) { + case legacy_hal::WIFI_ANTENNA_1X1: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_1X1; + case legacy_hal::WIFI_ANTENNA_2X2: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_2X2; + case legacy_hal::WIFI_ANTENNA_3X3: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_3X3; + case legacy_hal::WIFI_ANTENNA_4X4: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_4X4; + default: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED; + } +} + +bool convertLegacyWifiRadioConfigurationToHidl( + legacy_hal::wifi_radio_configuration* radio_configuration, + V1_6::WifiRadioConfiguration* hidl_radio_configuration) { + if (!hidl_radio_configuration) { + return false; + } + *hidl_radio_configuration = {}; + hidl_radio_configuration->bandInfo = + hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band); + if (hidl_radio_configuration->bandInfo == V1_5::WifiBand::BAND_UNSPECIFIED) { + LOG(ERROR) << "Unspecified band"; + return false; + } + hidl_radio_configuration->antennaMode = + hidl_struct_util::convertLegacyAntennaConfigurationToHidl( + radio_configuration->antenna_cfg); + return true; +} + +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + WifiRadioCombinationMatrix* hidl_matrix) { + if (!hidl_matrix || !legacy_matrix) { + return false; + } + *hidl_matrix = {}; + + int num_combinations = legacy_matrix->num_radio_combinations; + std::vector<V1_6::WifiRadioCombination> radio_combinations_vec; + if (!num_combinations) { + LOG(ERROR) << "zero radio combinations"; + return false; + } + wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations; + for (int i = 0; i < num_combinations; i++) { + int num_configurations = l_radio_combinations_ptr->num_radio_configurations; + WifiRadioCombination radioCombination; + std::vector<V1_6::WifiRadioConfiguration> radio_configurations_vec; + if (!num_configurations) { + LOG(ERROR) << "zero radio configurations"; + return false; + } + for (int j = 0; j < num_configurations; j++) { + WifiRadioConfiguration radioConfiguration; + wifi_radio_configuration* l_radio_configurations_ptr = + &l_radio_combinations_ptr->radio_configurations[j]; + if (!hidl_struct_util::convertLegacyWifiRadioConfigurationToHidl( + l_radio_configurations_ptr, &radioConfiguration)) { + LOG(ERROR) << "Error converting wifi radio configuration"; + return false; + } + radio_configurations_vec.push_back(radioConfiguration); + } + radioCombination.radioConfigurations = radio_configurations_vec; + radio_combinations_vec.push_back(radioCombination); + l_radio_combinations_ptr = + (wifi_radio_combination*)((u8*)l_radio_combinations_ptr + + sizeof(wifi_radio_combination) + + (sizeof(wifi_radio_configuration) * num_configurations)); + } + hidl_matrix->radioCombinations = radio_combinations_vec; + return true; +} + +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h new file mode 100644 index 0000000..2d4a5f1 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h @@ -0,0 +1,204 @@ +/* + * 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 <vector> + +#include <android/hardware/wifi/1.0/IWifiChip.h> +#include <android/hardware/wifi/1.0/types.h> +#include <android/hardware/wifi/1.2/types.h> +#include <android/hardware/wifi/1.3/types.h> +#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h> +#include <android/hardware/wifi/1.4/types.h> +#include <android/hardware/wifi/1.6/IWifiChip.h> +#include <android/hardware/wifi/1.6/types.h> + +#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_6 { +namespace implementation { +namespace hidl_struct_util { +using namespace android::hardware::wifi::V1_0; + +// Chip conversion methods. +bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set, + 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_hal::wifi_ring_buffer_status>& legacy_status_vec, + std::vector<WifiDebugRingBufferStatus>* hidl_status_vec); +bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario); +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + V1_3::IWifiChip::LatencyMode hidl_latency_mode); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario); +bool convertLegacyWifiMacInfosToHidl( + const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos, + std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos); +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type); +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + V1_5::IWifiChip::MultiStaUseCase use_case); +bool convertHidlCoexUnsafeChannelToLegacy( + const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel); +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels, + std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels); +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + V1_6::WifiRadioCombinationMatrix* hidl_matrix); +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band); +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg); + +// STA iface conversion methods. +bool convertLegacyFeaturesToHidlStaCapabilities(uint64_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(V1_0::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_hal::wifi_cached_scan_results>& legacy_cached_scan_results, + std::vector<StaScanData>* hidl_scan_datas); +bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats, + V1_6::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_hal::wifi_tx_report>& legacy_fates, + std::vector<WifiDebugTxPacketFateReport>* hidl_fates); +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector<legacy_hal::wifi_rx_report>& legacy_fates, + std::vector<WifiDebugRxPacketFateReport>* hidl_fates); + +// NAN iface conversion methods. +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, + WifiNanStatus* wifiNanStatus); +bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanEnableRequest_1_6ToLegacy( + const V1_4::NanEnableRequest& hidl_request1, + const V1_6::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequest_1_6ToLegacy( + const V1_4::NanConfigRequest& hidl_request1, + const V1_6::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanPublishRequestToLegacy(const V1_6::NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request); +bool convertHidlNanSubscribeRequestToLegacy(const V1_0::NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request); +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request); +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const V1_0::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponseToLegacy( + const V1_0::NanRespondToDataPathIndicationRequest& hidl_response, + legacy_hal::NanDataPathIndicationResponse* legacy_response); +bool convertHidlNanDataPathInitiatorRequest_1_6ToLegacy( + const V1_6::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponse_1_6ToLegacy( + const V1_6::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, + V1_6::NanCapabilities* hidl_response); +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + V1_6::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, + V1_6::NanDataPathConfirmInd* hidl_ind); +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_6::NanDataPathScheduleUpdateInd* hidl_ind); + +// RTT controller conversion methods. +bool convertHidlVectorOfRttConfigToLegacy(const std::vector<V1_6::RttConfig>& hidl_configs, + std::vector<legacy_hal::wifi_rtt_config>* 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 V1_6::RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder); +bool convertHidlWifiChannelInfoToLegacy(const V1_6::WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info); +bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder, + V1_6::RttResponder* hidl_responder); +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + V1_6::RttCapabilities* hidl_capabilities); +bool convertLegacyVectorOfRttResultToHidl( + const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results, + std::vector<V1_6::RttResult>* hidl_results); +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band); +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask); +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask); +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels, + std::vector<V1_6::WifiUsableChannel>* hidl_usable_channels); +bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + V1_6::StaPeerInfo* hidl_peer_info_stats); +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + V1_6::WifiRateInfo* hidl_rate); +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // HIDL_STRUCT_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp new file mode 100644 index 0000000..358d95e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/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_6 { +namespace implementation { +namespace hidl_sync_util { + +std::unique_lock<std::recursive_mutex> acquireGlobalLock() { + return std::unique_lock<std::recursive_mutex>{g_mutex}; +} + +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h new file mode 100644 index 0000000..2c1c37b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/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 <mutex> + +// 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_6 { +namespace implementation { +namespace hidl_sync_util { +std::unique_lock<std::recursive_mutex> acquireGlobalLock(); +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_SYNC_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp new file mode 100644 index 0000000..981bf7b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 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 <android-base/logging.h> + +#include "ringbuffer.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {} + +enum Ringbuffer::AppendStatus Ringbuffer::append(const std::vector<uint8_t>& input) { + if (input.size() == 0) { + return AppendStatus::FAIL_IP_BUFFER_ZERO; + } + if (input.size() > maxSize_) { + LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped"; + return AppendStatus::FAIL_IP_BUFFER_EXCEEDED_MAXSIZE; + } + data_.push_back(input); + size_ += input.size() * sizeof(input[0]); + while (size_ > maxSize_) { + if (data_.front().size() <= 0 || data_.front().size() > maxSize_) { + LOG(ERROR) << "First buffer in the ring buffer is Invalid. Size: " + << data_.front().size(); + return AppendStatus::FAIL_RING_BUFFER_CORRUPTED; + } + size_ -= data_.front().size() * sizeof(data_.front()[0]); + data_.pop_front(); + } + return AppendStatus::SUCCESS; +} + +const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const { + return data_; +} + +void Ringbuffer::clear() { + data_.clear(); + size_ = 0; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h new file mode 100644 index 0000000..c6a1e4c --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 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 RINGBUFFER_H_ +#define RINGBUFFER_H_ + +#include <list> +#include <vector> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * Ringbuffer object used to store debug data. + */ +class Ringbuffer { + public: + // Error codes for the append ring buffer operation + enum AppendStatus { + SUCCESS, + FAIL_GENERIC, + FAIL_IP_BUFFER_ZERO, + FAIL_IP_BUFFER_EXCEEDED_MAXSIZE, + FAIL_RING_BUFFER_CORRUPTED + }; + explicit Ringbuffer(size_t maxSize); + + // Appends the data buffer and deletes from the front until buffer is + // within |maxSize_|. + enum AppendStatus append(const std::vector<uint8_t>& input); + const std::list<std::vector<uint8_t>>& getData() const; + void clear(); + + private: + std::list<std::vector<uint8_t>> data_; + size_t size_; + size_t maxSize_; +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // RINGBUFFER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/service.cpp b/wifi/wifi_legacy_service/1.0-legacy/service.cpp new file mode 100644 index 0000000..c874d8b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/service.cpp @@ -0,0 +1,71 @@ +/* + * 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 <android-base/logging.h> +#include <hidl/HidlLazyUtils.h> +#include <hidl/HidlTransportSupport.h> +#include <signal.h> +#include <utils/Looper.h> +#include <utils/StrongPointer.h> + +#include "wifi.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" +#include "wifi_mode_controller.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::wifi::V1_6::implementation::feature_flags::WifiFeatureFlags; +using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHal; +using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHalFactory; +using android::hardware::wifi::V1_6::implementation::mode_controller::WifiModeController; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main(int /*argc*/, char** argv) { + signal(SIGPIPE, SIG_IGN); + android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + LOG(INFO) << "Wifi Hal is booting up..."; + + configureRpcThreadpool(1, true /* callerWillJoin */); + + const auto iface_tool = std::make_shared<android::wifi_system::InterfaceTool>(); + const auto legacy_hal_factory = std::make_shared<WifiLegacyHalFactory>(iface_tool); + + // Setup hwbinder service + android::sp<android::hardware::wifi::V1_6::IWifi> service = + new android::hardware::wifi::V1_6::implementation::Wifi( + iface_tool, legacy_hal_factory, std::make_shared<WifiModeController>(), + std::make_shared<WifiFeatureFlags>()); + if (kLazyService) { + auto registrar = LazyServiceRegistrar::getInstance(); + CHECK_EQ(registrar.registerService(service), android::NO_ERROR) + << "Failed to register wifi HAL"; + } else { + 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/wifi_legacy_service/1.0-legacy/wifi.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi.cpp new file mode 100644 index 0000000..c302ce2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi.cpp @@ -0,0 +1,294 @@ +/* + * 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 <android-base/logging.h> + +#include "hidl_return_util.h" +#include "wifi.h" +#include "wifi_status_util.h" + +namespace { +// Starting Chip ID, will be assigned to primary chip +static constexpr android::hardware::wifi::V1_0::ChipId kPrimaryChipId = 0; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +Wifi::Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool, + const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory, + const std::shared_ptr<mode_controller::WifiModeController> mode_controller, + const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags) + : iface_tool_(iface_tool), + legacy_hal_factory_(legacy_hal_factory), + mode_controller_(mode_controller), + feature_flags_(feature_flags), + run_state_(RunState::STOPPED) {} + +bool Wifi::isValid() { + // This object is always valid. + return true; +} + +Return<void> Wifi::registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal, hidl_status_cb, event_callback); +} + +Return<void> Wifi::registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal_1_5, hidl_status_cb, + event_callback); +} + +Return<bool> Wifi::isStarted() { + return run_state_ != RunState::STOPPED; +} + +Return<void> Wifi::start(start_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal, + hidl_status_cb); +} + +Return<void> Wifi::stop(stop_cb hidl_status_cb) { + return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, + hidl_status_cb); +} + +Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal, + hidl_status_cb); +} + +Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal, + hidl_status_cb, chip_id); +} + +Return<void> Wifi::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) { + LOG(INFO) << "-----------Debug is called----------------"; + if (chips_.size() == 0) { + return Void(); + } + + for (sp<WifiChip> chip : chips_) { + if (!chip.get()) continue; + + chip->debug(handle, {}); + } + return Void(); +} + +WifiStatus Wifi::registerEventCallbackInternal( + const sp<V1_0::IWifiEventCallback>& event_callback __unused) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus Wifi::registerEventCallbackInternal_1_5( + const sp<V1_5::IWifiEventCallback>& 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 = initializeModeControllerAndLegacyHal(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Register the callback for subsystem restart + const auto& on_subsystem_restart_callback = [this](const std::string& error) { + WifiStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + LOG(INFO) << "Attempting to invoke onSubsystemRestart " + "callback"; + if (!callback->onSubsystemRestart(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onSubsystemRestart callback"; + } else { + LOG(INFO) << "Succeeded to invoke onSubsystemRestart " + "callback"; + } + } + }; + + // Create the chip instance once the HAL is started. + android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId; + for (auto& hal : legacy_hals_) { + chips_.push_back( + new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_, + std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal), + feature_flags_, on_subsystem_restart_callback)); + chipId++; + } + run_state_ = RunState::STARTED; + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStart().isOk()) { + LOG(ERROR) << "Failed to invoke onStart callback"; + }; + } + LOG(INFO) << "Wifi HAL started"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL start failed"; + // Clear the event callback objects since the HAL start failed. + event_cb_handler_.invalidate(); + } + return wifi_status; +} + +WifiStatus Wifi::stopInternal( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) { + if (run_state_ == RunState::STOPPED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); + } + // Clear the chip object and its child objects since the HAL is now + // stopped. + for (auto& chip : chips_) { + if (chip.get()) { + chip->invalidate(); + chip.clear(); + } + } + chips_.clear(); + WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock); + 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"; + }; + } + LOG(INFO) << "Wifi HAL stopped"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL stop failed"; + } + // Clear the event callback objects since the HAL is now stopped. + event_cb_handler_.invalidate(); + return wifi_status; +} + +std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() { + std::vector<ChipId> chip_ids; + + for (auto& chip : chips_) { + ChipId chip_id = getChipIdFromWifiChip(chip); + if (chip_id != UINT32_MAX) chip_ids.emplace_back(chip_id); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)}; +} + +std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(ChipId chip_id) { + for (auto& chip : chips_) { + ChipId cand_id = getChipIdFromWifiChip(chip); + if ((cand_id != UINT32_MAX) && (cand_id == chip_id)) + return {createWifiStatus(WifiStatusCode::SUCCESS), chip}; + } + + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; +} + +WifiStatus Wifi::initializeModeControllerAndLegacyHal() { + if (!mode_controller_->initialize()) { + LOG(ERROR) << "Failed to initialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + + legacy_hals_ = legacy_hal_factory_->getHals(); + if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + int index = 0; // for failure log + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error legacy_status = hal->initialize(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // Currently WifiLegacyHal::initialize does not allocate extra mem, + // only initializes the function table. If this changes, need to + // implement WifiLegacyHal::deinitialize and deinitalize the + // HALs already initialized + LOG(ERROR) << "Failed to initialize legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + index++; + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) { + legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS; + int index = 0; + + run_state_ = RunState::STOPPING; + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {}); + if (tmp != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + legacy_status = tmp; + } + index++; + } + run_state_ = RunState::STOPPED; + + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "One or more legacy HALs failed to stop"; + 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); +} + +ChipId Wifi::getChipIdFromWifiChip(sp<WifiChip>& chip) { + ChipId chip_id = UINT32_MAX; + if (chip.get()) { + chip->getId([&](WifiStatus status, uint32_t id) { + if (status.code == WifiStatusCode::SUCCESS) { + chip_id = id; + } + }); + } + + return chip_id; +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi.h b/wifi/wifi_legacy_service/1.0-legacy/wifi.h new file mode 100644 index 0000000..435358e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi.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_H_ +#define WIFI_H_ + +// HACK: NAN is a macro defined in math.h, which can be included in various +// headers. This wifi HAL uses an enum called NAN, which does not compile when +// the macro is defined. Undefine NAN to work around it. +#undef NAN +#include <android/hardware/wifi/1.6/IWifi.h> + +#include <android-base/macros.h> +#include <utils/Looper.h> +#include <functional> + +#include "hidl_callback_util.h" +#include "wifi_chip.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" +#include "wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * Root HIDL interface object used to control the Wifi HAL. + */ +class Wifi : public V1_6::IWifi { + public: + Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool, + const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory, + const std::shared_ptr<mode_controller::WifiModeController> mode_controller, + const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags); + + bool isValid(); + + // HIDL methods exposed. + Return<void> registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) override; + Return<bool> isStarted() override; + Return<void> start(start_cb hidl_status_cb) override; + Return<void> stop(stop_cb hidl_status_cb) override; + Return<void> getChipIds(getChipIds_cb hidl_status_cb) override; + Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override; + Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override; + + private: + enum class RunState { STOPPED, STARTED, STOPPING }; + + // Corresponding worker functions for the HIDL methods. + WifiStatus registerEventCallbackInternal( + const sp<V1_0::IWifiEventCallback>& event_callback __unused); + WifiStatus registerEventCallbackInternal_1_5( + const sp<V1_5::IWifiEventCallback>& event_callback); + WifiStatus startInternal(); + WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock); + std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal(); + std::pair<WifiStatus, sp<V1_4::IWifiChip>> getChipInternal(ChipId chip_id); + + WifiStatus initializeModeControllerAndLegacyHal(); + WifiStatus stopLegacyHalAndDeinitializeModeController( + std::unique_lock<std::recursive_mutex>* lock); + ChipId getChipIdFromWifiChip(sp<WifiChip>& chip); + + // Instance is created in this root level |IWifi| HIDL interface object + // and shared with all the child HIDL interface objects. + std::shared_ptr<wifi_system::InterfaceTool> iface_tool_; + std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory_; + std::shared_ptr<mode_controller::WifiModeController> mode_controller_; + std::vector<std::shared_ptr<legacy_hal::WifiLegacyHal>> legacy_hals_; + std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_; + RunState run_state_; + std::vector<sp<WifiChip>> chips_; + hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback> event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(Wifi); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp new file mode 100644 index 0000000..b2957db --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp @@ -0,0 +1,204 @@ +/* + * 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 <android-base/logging.h> + +#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_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) + : ifname_(ifname), + instances_(instances), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) {} + +void WifiApIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiApIface::isValid() { + return is_valid_; +} + +std::string WifiApIface::getName() { + return ifname_; +} + +void WifiApIface::removeInstance(std::string instance) { + instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end()); +} + +Return<void> WifiApIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiApIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setCountryCodeInternal, hidl_status_cb, code); +} + +Return<void> WifiApIface::getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getValidFrequenciesForBandInternal, hidl_status_cb, band); +} + +Return<void> WifiApIface::setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setMacAddressInternal, hidl_status_cb, mac); +} + +Return<void> WifiApIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getFactoryMacAddressInternal, hidl_status_cb, + instances_.size() > 0 ? instances_[0] : ifname_); +} + +Return<void> WifiApIface::resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::resetToFactoryMacAddressInternal, hidl_status_cb); +} + +Return<void> WifiApIface::getBridgedInstances(getBridgedInstances_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getBridgedInstancesInternal, hidl_status_cb); +} + +std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiApIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP}; +} + +WifiStatus WifiApIface::setCountryCodeInternal(const std::array<int8_t, 2>& code) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode( + instances_.size() > 0 ? instances_[0] : ifname_, code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<WifiChannelInMhz>> +WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector<uint32_t> valid_frequencies; + std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand( + instances_.size() > 0 ? instances_[0] : ifname_, + hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} + +WifiStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) { + // Support random MAC up to 2 interfaces + if (instances_.size() == 2) { + int rbyte = 1; + for (auto const& intf : instances_) { + std::array<uint8_t, 6> rmac = mac; + // reverse the bits to avoid collision + rmac[rbyte] = 0xff - rmac[rbyte]; + if (!iface_util_.lock()->setMacAddress(intf, rmac)) { + LOG(INFO) << "Failed to set random mac address on " << intf; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + rbyte++; + } + } + // It also needs to set mac address for bridged interface, otherwise the mac + // address of bridged interface will be changed after one of instance + // down. + if (!iface_util_.lock()->setMacAddress(ifname_, mac)) { + LOG(ERROR) << "Fail to config MAC for interface " << ifname_; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, std::array<uint8_t, 6>> WifiApIface::getFactoryMacAddressInternal( + const std::string& ifaceName) { + std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifaceName); + if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; +} + +WifiStatus WifiApIface::resetToFactoryMacAddressInternal() { + std::pair<WifiStatus, std::array<uint8_t, 6>> getMacResult; + if (instances_.size() == 2) { + for (auto const& intf : instances_) { + getMacResult = getFactoryMacAddressInternal(intf); + LOG(DEBUG) << "Reset MAC to factory MAC on " << intf; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(intf, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + // It needs to set mac address for bridged interface, otherwise the mac + // address of the bridged interface will be changed after one of the + // instance down. Thus we are generating a random MAC address for the + // bridged interface even if we got the request to reset the Factory + // MAC. Since the bridged interface is an internal interface for the + // operation of bpf and others networking operation. + if (!iface_util_.lock()->setMacAddress(ifname_, + iface_util_.lock()->createRandomMacAddress())) { + LOG(ERROR) << "Fail to config MAC for bridged interface " << ifname_; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } else { + getMacResult = getFactoryMacAddressInternal(ifname_); + LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(ifname_, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, std::vector<hidl_string>> WifiApIface::getBridgedInstancesInternal() { + std::vector<hidl_string> instances; + for (const auto& instance_name : instances_) { + instances.push_back(instance_name); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), instances}; +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h new file mode 100644 index 0000000..d1c0642 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h @@ -0,0 +1,89 @@ +/* + * 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 <android-base/macros.h> +#include <android/hardware/wifi/1.5/IWifiApIface.h> + +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a AP Iface instance. + */ +class WifiApIface : public V1_5::IWifiApIface { + public: + WifiApIface(const std::string& ifname, const std::vector<std::string>& instances, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + void removeInstance(std::string instance); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb hidl_status_cb) override; + Return<void> getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) override; + Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) override; + Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override; + Return<void> resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) override; + + Return<void> getBridgedInstances(getBridgedInstances_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code); + std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal( + V1_0::WifiBand band); + WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac); + std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal( + const std::string& ifaceName); + WifiStatus resetToFactoryMacAddressInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getBridgedInstancesInternal(); + + std::string ifname_; + std::vector<std::string> instances_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiApIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_AP_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp new file mode 100644 index 0000000..08ef368 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp @@ -0,0 +1,2109 @@ +/* + * 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 <fcntl.h> + +#include <android-base/logging.h> +#include <android-base/unique_fd.h> +#include <cutils/properties.h> +#include <net/if.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_chip.h" +#include "wifi_status_util.h" + +#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-" + +namespace { +using android::sp; +using android::base::unique_fd; +using android::hardware::hidl_string; +using android::hardware::hidl_vec; +using android::hardware::wifi::V1_0::ChipModeId; +using android::hardware::wifi::V1_0::IfaceType; +using android::hardware::wifi::V1_0::IWifiChip; + +constexpr char kCpioMagic[] = "070701"; +constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3; +constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10; +constexpr uint32_t kMaxRingBufferFileNum = 20; +constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/"; +constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface"; +constexpr char kNoActiveWlanIfaceNamePropertyValue[] = ""; +constexpr unsigned kMaxWlanIfaces = 5; +constexpr char kApBridgeIfacePrefix[] = "ap_br_"; + +template <typename Iface> +void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) { + iface->invalidate(); + ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end()); +} + +template <typename Iface> +void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) { + for (const auto& iface : ifaces) { + iface->invalidate(); + } + ifaces.clear(); +} + +template <typename Iface> +std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) { + std::vector<hidl_string> names; + for (const auto& iface : ifaces) { + names.emplace_back(iface->getName()); + } + return names; +} + +template <typename Iface> +sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces, const std::string& name) { + std::vector<hidl_string> names; + for (const auto& iface : ifaces) { + if (name == iface->getName()) { + return iface; + } + } + return nullptr; +} + +std::string getWlanIfaceName(unsigned idx) { + if (idx >= kMaxWlanIfaces) { + CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces; + return {}; + } + + std::array<char, PROPERTY_VALUE_MAX> buffer; + if (idx == 0 || idx == 1) { + const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface"; + auto res = property_get(altPropName, buffer.data(), nullptr); + if (res > 0) return buffer.data(); + } + std::string propName = "wifi.interface." + std::to_string(idx); + auto res = property_get(propName.c_str(), buffer.data(), nullptr); + if (res > 0) return buffer.data(); + + return "wlan" + std::to_string(idx); +} + +// Returns the dedicated iface name if defined. +// Returns two ifaces in bridged mode. +std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) { + std::vector<std::string> ifnames; + std::array<char, PROPERTY_VALUE_MAX> buffer; + buffer.fill(0); + if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) { + return ifnames; + } + ifnames.push_back(buffer.data()); + if (is_bridged) { + buffer.fill(0); + if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) { + return ifnames; + } + ifnames.push_back(buffer.data()); + } + return ifnames; +} + +std::string getPredefinedP2pIfaceName() { + std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName; + char p2pParentIfname[100]; + std::string p2pDevIfName = ""; + std::array<char, PROPERTY_VALUE_MAX> buffer; + property_get("wifi.direct.interface", buffer.data(), "p2p0"); + if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) { + /* Get the p2p parent interface name from p2p device interface name set + * in property */ + strlcpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX), + strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)); + if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(), nullptr) == 0) { + return buffer.data(); + } + /* Check if the parent interface derived from p2p device interface name + * is active */ + if (strncmp(p2pParentIfname, primaryIfaceName.data(), + strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) != 0) { + /* + * Update the predefined p2p device interface parent interface name + * with current active wlan interface + */ + p2pDevIfName += P2P_MGMT_DEVICE_PREFIX; + p2pDevIfName += primaryIfaceName.data(); + LOG(INFO) << "update the p2p device interface name to " << p2pDevIfName.c_str(); + return p2pDevIfName; + } + } + return buffer.data(); +} + +// Returns the dedicated iface name if one is defined. +std::string getPredefinedNanIfaceName() { + std::array<char, PROPERTY_VALUE_MAX> buffer; + if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) { + return {}; + } + return buffer.data(); +} + +void setActiveWlanIfaceNameProperty(const std::string& ifname) { + auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data()); + if (res != 0) { + PLOG(ERROR) << "Failed to set active wlan iface name property"; + } +} + +// delete files that meet either conditions: +// 1. older than a predefined time in the wifi tombstone dir. +// 2. Files in excess to a predefined amount, starting from the oldest ones +bool removeOldFilesInternal() { + time_t now = time(0); + const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds; + std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(kTombstoneFolderPath), closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return false; + } + struct dirent* dp; + bool success = true; + std::list<std::pair<const time_t, std::string>> valid_files; + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + struct stat cur_file_stat; + std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + success = false; + continue; + } + const time_t cur_file_time = cur_file_stat.st_mtime; + valid_files.push_back(std::pair<const time_t, std::string>(cur_file_time, cur_file_path)); + } + valid_files.sort(); // sort the list of files by last modified time from + // small to big. + uint32_t cur_file_count = valid_files.size(); + for (auto cur_file : valid_files) { + if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) { + if (unlink(cur_file.second.c_str()) != 0) { + PLOG(ERROR) << "Error deleting file"; + success = false; + } + cur_file_count--; + } else { + break; + } + } + return success; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) { + const int buf_size = 32 * 1024; + std::array<char, buf_size> read_buf; + ssize_t llen = snprintf( + read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X", + kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid, + static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime), + static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev), + minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0); + if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) { + PLOG(ERROR) << "Error writing cpio header to file " << file_name; + return false; + } + if (write(out_fd, file_name, file_name_len) == -1) { + PLOG(ERROR) << "Error writing filename to file " << file_name; + return false; + } + + // NUL Pad header up to 4 multiple bytes. + llen = (llen + file_name_len) % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file " << file_name; + return false; + } + } + return true; +} + +// Helper function for |cpioArchiveFilesInDir| +size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) { + // writing content of file + std::array<char, 32 * 1024> read_buf; + ssize_t llen = st.st_size; + size_t n_error = 0; + while (llen > 0) { + ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size()); + if (bytes_read == -1) { + PLOG(ERROR) << "Error reading file"; + return ++n_error; + } + llen -= bytes_read; + if (write(out_fd, read_buf.data(), bytes_read) == -1) { + PLOG(ERROR) << "Error writing data to file"; + return ++n_error; + } + if (bytes_read == 0) { // this should never happen, but just in case + // to unstuck from while loop + PLOG(ERROR) << "Unexpected read result"; + n_error++; + break; + } + } + llen = st.st_size % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file"; + return ++n_error; + } + } + return n_error; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteFileTrailer(int out_fd) { + const int buf_size = 4096; + std::array<char, buf_size> read_buf; + read_buf.fill(0); + ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0); + if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) { + PLOG(ERROR) << "Error writing trailing bytes"; + return false; + } + return true; +} + +// Archives all files in |input_dir| and writes result into |out_fd| +// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive" +// portion +size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { + struct dirent* dp; + size_t n_error = 0; + std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return ++n_error; + } + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + struct stat st; + const std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &st) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + n_error++; + continue; + } + const int fd_read = open(cur_file_path.c_str(), O_RDONLY); + if (fd_read == -1) { + PLOG(ERROR) << "Failed to open file " << cur_file_path; + n_error++; + continue; + } + std::string file_name_with_last_modified_time = + cur_file_name + "-" + std::to_string(st.st_mtime); + // string.size() does not include the null terminator. The cpio FreeBSD + // file header expects the null character to be included in the length. + const size_t file_name_len = file_name_with_last_modified_time.size() + 1; + unique_fd file_auto_closer(fd_read); + if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(), + file_name_len)) { + return ++n_error; + } + size_t write_error = cpioWriteFileContent(fd_read, out_fd, st); + if (write_error) { + return n_error + write_error; + } + } + if (!cpioWriteFileTrailer(out_fd)) { + return ++n_error; + } + return n_error; +} + +// Helper function to create a non-const char*. +std::vector<char> makeCharVec(const std::string& str) { + std::vector<char> 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_6 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +WifiChip::WifiChip(ChipId chip_id, bool is_primary, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<mode_controller::WifiModeController> mode_controller, + const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags, + const std::function<void(const std::string&)>& handler) + : chip_id_(chip_id), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + iface_util_(iface_util), + is_valid_(true), + current_mode_id_(feature_flags::chip_mode_ids::kInvalid), + modes_(feature_flags.lock()->getChipModes(is_primary)), + debug_ring_buffer_cb_registered_(false), + subsystemCallbackHandler_(handler) { + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); +} + +void WifiChip::invalidate() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + invalidateAndRemoveAllIfaces(); + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiChip::isValid() { + return is_valid_; +} + +std::set<sp<V1_4::IWifiChipEventCallback>> WifiChip::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return<void> WifiChip::getId(getId_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal, + hidl_status_cb); +} + +// Deprecated support for this callback +Return<void> WifiChip::registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal, hidl_status_cb, + event_callback); +} + +Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal, hidl_status_cb); +} + +Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) { + return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::configureChipInternal, hidl_status_cb, mode_id); +} + +Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getModeInternal, hidl_status_cb); +} + +Return<void> WifiChip::requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestChipDebugInfoInternal, hidl_status_cb); +} + +Return<void> WifiChip::requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestDriverDebugDumpInternal, hidl_status_cb); +} + +Return<void> WifiChip::requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestFirmwareDebugDumpInternal, hidl_status_cb); +} + +Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createApIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::createBridgedApIface(createBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createBridgedApIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceNamesInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiChip::removeIfaceInstanceFromBridgedApIface( + const hidl_string& ifname, const hidl_string& ifInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, hidl_status_cb, + ifname, ifInstanceName); +} + +Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createNanIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceNamesInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createP2pIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createStaIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceNamesInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiChip::createRttController(const sp<IWifiIface>& bound_iface, + createRttController_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal, hidl_status_cb, bound_iface); +} + +Return<void> WifiChip::getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugRingBuffersStatusInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiChip::flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::flushRingBufferToFileInternal, hidl_status_cb); +} + +Return<void> WifiChip::stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::stopLoggingToDebugRingBufferInternal, hidl_status_cb); +} + +Return<void> WifiChip::getDebugHostWakeReasonStats(getDebugHostWakeReasonStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugHostWakeReasonStatsInternal, hidl_status_cb); +} + +Return<void> WifiChip::enableDebugErrorAlerts(bool enable, + enableDebugErrorAlerts_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::enableDebugErrorAlertsInternal, hidl_status_cb, enable); +} + +Return<void> WifiChip::selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal, hidl_status_cb, scenario); +} + +Return<void> WifiChip::resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::resetTxPowerScenarioInternal, hidl_status_cb); +} + +Return<void> WifiChip::setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setLatencyModeInternal, hidl_status_cb, mode); +} + +Return<void> WifiChip::registerEventCallback_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal_1_2, hidl_status_cb, + event_callback); +} + +Return<void> WifiChip::selectTxPowerScenario_1_2(TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario); +} + +Return<void> WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_3, hidl_status_cb); +} + +Return<void> WifiChip::getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_5, hidl_status_cb); +} + +Return<void> WifiChip::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) { + if (handle != nullptr && handle->numFds >= 1) { + { + std::unique_lock<std::mutex> lk(lock_t); + for (const auto& item : ringbuffer_map_) { + forceDumpToDebugRingBufferInternal(item.first); + } + // unique_lock unlocked here + } + usleep(100 * 1000); // sleep for 100 milliseconds to wait for + // ringbuffer updates. + int fd = handle->data[0]; + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath); + if (n_error != 0) { + LOG(ERROR) << n_error << " errors occured in cpio function"; + } + fsync(fd); + } else { + LOG(ERROR) << "File handle error"; + } + return Void(); +} + +Return<void> WifiChip::createRttController_1_4(const sp<IWifiIface>& bound_iface, + createRttController_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal_1_4, hidl_status_cb, bound_iface); +} + +Return<void> WifiChip::registerEventCallback_1_4( + const sp<V1_4::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal_1_4, hidl_status_cb, + event_callback); +} + +Return<void> WifiChip::setMultiStaPrimaryConnection( + const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaPrimaryConnectionInternal, hidl_status_cb, ifname); +} + +Return<void> WifiChip::setMultiStaUseCase(MultiStaUseCase use_case, + setMultiStaUseCase_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaUseCaseInternal, hidl_status_cb, use_case); +} + +Return<void> WifiChip::setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafeChannels, + hidl_bitfield<CoexRestriction> restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setCoexUnsafeChannelsInternal, hidl_status_cb, unsafeChannels, + restrictions); +} + +Return<void> WifiChip::setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiChip::setCountryCodeInternal, hidl_status_cb, code); +} + +Return<void> WifiChip::getUsableChannels( + WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask, + hidl_bitfield<V1_5::IWifiChip::UsableChannelFilter> filterMask, + getUsableChannels_cb _hidl_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getUsableChannelsInternal, _hidl_cb, band, ifaceModeMask, + filterMask); +} + +Return<void> WifiChip::triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::triggerSubsystemRestartInternal, hidl_status_cb); +} + +Return<void> WifiChip::createRttController_1_6(const sp<IWifiIface>& bound_iface, + createRttController_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal_1_6, hidl_status_cb, bound_iface); +} + +Return<void> WifiChip::getUsableChannels_1_6( + WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask, + hidl_bitfield<V1_6::IWifiChip::UsableChannelFilter> filterMask, + getUsableChannels_1_6_cb _hidl_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getUsableChannelsInternal_1_6, _hidl_cb, band, ifaceModeMask, + filterMask); +} + +Return<void> WifiChip::getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getSupportedRadioCombinationsMatrixInternal, hidl_status_cb); +} + +Return<void> WifiChip::getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal_1_6, hidl_status_cb); +} + +void WifiChip::QcRemoveAndClearDynamicIfaces() { + for (const auto& iface : created_ap_ifaces_) { + std::string ifname = iface->getName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + } + + for (const auto& iface : created_sta_ifaces_) { + std::string ifname = iface->getName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + } + + // created_ap/sta_ifaces are also part of sta/ap_ifaces. + // Do no invalidate here. + + created_ap_ifaces_.clear(); + created_sta_ifaces_.clear(); +} + +void WifiChip::invalidateAndRemoveAllIfaces() { + QcRemoveAndClearDynamicIfaces(); + invalidateAndClearBridgedApAll(); + invalidateAndClearAll(ap_ifaces_); + invalidateAndClearAll(nan_ifaces_); + invalidateAndClearAll(p2p_ifaces_); + invalidateAndClearAll(sta_ifaces_); + // 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(); +} + +void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) { + for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) { + auto nan_iface = *it; + if (nan_iface->getName() == removed_iface_name) { + nan_iface->invalidate(); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::NAN, removed_iface_name).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + it = nan_ifaces_.erase(it); + } else { + ++it; + } + } + + for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) { + auto rtt = *it; + if (rtt->getIfaceName() == removed_iface_name) { + rtt->invalidate(); + it = rtt_controllers_.erase(it); + } else { + ++it; + } + } +} + +std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_}; +} + +WifiStatus WifiChip::registerEventCallbackInternal( + const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair<WifiStatus, std::vector<V1_0::IWifiChip::ChipMode>> +WifiChip::getAvailableModesInternal() { + // Deprecated support -- use getAvailableModes_1_6 for more granular concurrency combinations. + std::vector<V1_0::IWifiChip::ChipMode> modes_1_0 = {}; + for (const auto& mode_1_6 : modes_) { + std::vector<V1_0::IWifiChip::ChipIfaceCombination> combos_1_0; + for (const auto& combo_1_6 : mode_1_6.availableCombinations) { + std::vector<V1_0::IWifiChip::ChipIfaceCombinationLimit> limits_1_0; + for (const auto& limit_1_6 : combo_1_6.limits) { + std::vector<IfaceType> types_1_0; + for (IfaceConcurrencyType type_1_6 : limit_1_6.types) { + switch (type_1_6) { + case IfaceConcurrencyType::STA: + types_1_0.push_back(IfaceType::STA); + break; + case IfaceConcurrencyType::AP: + types_1_0.push_back(IfaceType::AP); + break; + case IfaceConcurrencyType::AP_BRIDGED: + // Ignore AP_BRIDGED + break; + case IfaceConcurrencyType::P2P: + types_1_0.push_back(IfaceType::P2P); + break; + case IfaceConcurrencyType::NAN: + types_1_0.push_back(IfaceType::NAN); + break; + } + } + if (types_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipIfaceCombinationLimit limit_1_0; + limit_1_0.types = hidl_vec(types_1_0); + limit_1_0.maxIfaces = limit_1_6.maxIfaces; + limits_1_0.push_back(limit_1_0); + } + if (limits_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipIfaceCombination combo_1_0; + combo_1_0.limits = hidl_vec(limits_1_0); + combos_1_0.push_back(combo_1_0); + } + if (combos_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipMode mode_1_0; + mode_1_0.id = mode_1_6.id; + mode_1_0.availableCombinations = hidl_vec(combos_1_0); + modes_1_0.push_back(mode_1_0); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), modes_1_0}; +} + +WifiStatus WifiChip::configureChipInternal( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) { + if (!isValidModeId(mode_id)) { + 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(lock, 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; + LOG(INFO) << "Configured chip in mode " << mode_id; + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_); + + return status; +} + +std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() { + if (!isValidModeId(current_mode_id_)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), current_mode_id_}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; +} + +std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> WifiChip::requestChipDebugInfoInternal() { + V1_4::IWifiChip::ChipDebugInfo result; + legacy_hal::wifi_error legacy_status; + std::string driver_desc; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname); + 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(ifname); + 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<WifiStatus, std::vector<uint8_t>> WifiChip::requestDriverDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<uint8_t> driver_dump; + std::tie(legacy_status, driver_dump) = + legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), std::vector<uint8_t>()}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump}; +} + +std::pair<WifiStatus, std::vector<uint8_t>> WifiChip::requestFirmwareDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<uint8_t> firmware_dump; + std::tie(legacy_status, firmware_dump) = + legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName()); + 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}; +} + +WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) { + legacy_hal::wifi_error legacy_status; + legacy_status = legacy_hal_.lock()->createVirtualInterface( + apVirtIf, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << apVirtIf << " " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +sp<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) { + std::vector<std::string> ap_instances; + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + ap_instances = it.second; + } + } + sp<WifiApIface> iface = new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_); + ap_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return iface; +} + +std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createApIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool iface_created = false; + std::string ifname = allocateApIfaceName(); + if (!if_nametoindex(ifname.c_str())) { + WifiStatus status = createVirtualApInterface(ifname); + if (status.code != WifiStatusCode::SUCCESS) { + return {status, {}}; + } + iface_created = true; + } + sp<WifiApIface> iface = newWifiApIface(ifname); + if (iface_created) created_ap_ifaces_.push_back(iface); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createBridgedApIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::vector<std::string> ap_instances = allocateBridgedApInstanceNames(); + if (ap_instances.size() < 2) { + LOG(ERROR) << "Fail to allocate two instances"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0]; + for (int i = 0; i < 2; i++) { + WifiStatus status = createVirtualApInterface(ap_instances[i]); + if (status.code != WifiStatusCode::SUCCESS) { + if (i != 0) { // The failure happened when creating second virtual + // iface. + legacy_hal_.lock()->deleteVirtualInterface( + ap_instances.front()); // Remove the first virtual iface. + } + return {status, {}}; + } + } + br_ifaces_ap_instances_[br_ifname] = ap_instances; + if (!iface_util_->createBridge(br_ifname)) { + LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str(); + deleteApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + for (auto const& instance : ap_instances) { + // Bind ap instance interface to AP bridge + if (!iface_util_->addIfaceToBridge(br_ifname, instance)) { + LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str(); + deleteApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + } + sp<WifiApIface> iface = newWifiApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getApIfaceNamesInternal() { + if (ap_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)}; +} + +std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::getApIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + // Note: This is probably not required because we never create + // nan/rtt objects over AP iface. But, there is no harm to do it + // here and not make that assumption all over the place. + invalidateAndRemoveDependencies(ifname); + if (findUsingName(created_ap_ifaces_, ifname) != nullptr) { + invalidateAndClear(created_ap_ifaces_, iface); + } + invalidateAndClear(ap_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal( + const std::string& ifname, const std::string& ifInstanceName) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get() || ifInstanceName.empty()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Requires to remove one of the instance in bridge mode + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + std::vector<std::string> ap_instances = it.second; + for (auto const& iface : ap_instances) { + if (iface == ifInstanceName) { + if (!iface_util_->removeIfaceFromBridge(it.first, iface)) { + LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from " + << ifname; + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(iface); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to del interface: " << iface << " " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + ap_instances.erase( + std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName), + ap_instances.end()); + br_ifaces_ap_instances_[ifname] = ap_instances; + break; + } + } + break; + } + } + iface->removeInstance(ifInstanceName); + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::createNanIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool is_dedicated_iface = true; + std::string ifname = getPredefinedNanIfaceName(); + if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) { + // Use the first shared STA iface (wlan0) if a dedicated aware iface is + // not defined. + ifname = getFirstActiveWlanIfaceName(); + is_dedicated_iface = false; + } + sp<WifiNanIface> iface = new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_); + nan_ifaces_.push_back(iface); + 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), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getNanIfaceNamesInternal() { + if (nan_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)}; +} + +std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::getNanIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(nan_ifaces_, 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<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = getPredefinedP2pIfaceName(); + sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_); + p2p_ifaces_.push_back(iface); + 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), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getP2pIfaceNamesInternal() { + if (p2p_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)}; +} + +std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(p2p_ifaces_, 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<WifiStatus, sp<V1_6::IWifiStaIface>> WifiChip::createStaIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool iface_created = false; + std::string ifname = allocateStaIfaceName(); + if (!if_nametoindex(ifname.c_str())) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->createVirtualInterface( + ifname, + hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << ifname << " " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + iface_created = true; + } + sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); + sta_ifaces_.push_back(iface); + if (iface_created) created_sta_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getStaIfaceNamesInternal() { + if (sta_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)}; +} + +std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> WifiChip::getStaIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + invalidateAndRemoveDependencies(ifname); + if (findUsingName(created_sta_ifaces_, ifname) != nullptr) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + invalidateAndClear(created_sta_ifaces_, iface); + } + invalidateAndClear(sta_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<V1_0::IWifiRttController>> WifiChip::createRttControllerInternal( + const sp<IWifiIface>& /*bound_iface*/) { + LOG(ERROR) << "createRttController is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>> +WifiChip::getDebugRingBuffersStatusInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec; + std::tie(legacy_status, legacy_ring_buffer_status_vec) = + legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugRingBufferStatus> 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( + getFirstActiveWlanIfaceName(), ring_name, + static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level), + max_interval_in_sec, min_data_size_in_bytes); + ringbuffer_map_.insert( + std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes))); + // if verbose logging enabled, turn up HAL daemon logging as well. + if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) { + android::base::SetMinimumLogSeverity(android::base::DEBUG); + } else { + android::base::SetMinimumLogSeverity(android::base::VERBOSE); + } + 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(getFirstActiveWlanIfaceName(), ring_name); + + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::flushRingBufferToFileInternal() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName()); + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = false; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, WifiDebugHostWakeReasonStats> +WifiChip::getDebugHostWakeReasonStatsInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::WakeReasonStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName()); + 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<WifiChip> weak_ptr_this(this); + const auto& on_alert_callback = [weak_ptr_this](int32_t error_code, + std::vector<uint8_t> 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( + getFirstActiveWlanIfaceName(), on_alert_callback); + } else { + legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler( + getFirstActiveWlanIfaceName()); + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::resetTxPowerScenarioInternal() { + auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName()); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) { + auto legacy_status = legacy_hal_.lock()->setLatencyMode( + getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlLatencyModeToLegacy(mode)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerEventCallbackInternal_1_2( + const sp<V1_2::IWifiChipEventCallback>& /* event_callback */) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_3() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_5() { + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + uint32_t legacy_logger_feature_set; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname); + 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::convertLegacyFeaturesToHidlChipCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair<WifiStatus, sp<V1_4::IWifiRttController>> WifiChip::createRttControllerInternal_1_4( + const sp<IWifiIface>& /*bound_iface*/) { + LOG(ERROR) << "createRttController_1_4 is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiChip::registerEventCallbackInternal_1_4( + const sp<V1_4::IWifiChipEventCallback>& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) { + auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) { + auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase( + hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels, + uint32_t restrictions) { + std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels; + if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels, + &legacy_unsafe_channels)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + uint32_t legacy_restrictions = 0; + if (restrictions & CoexRestriction::WIFI_DIRECT) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT; + } + if (restrictions & CoexRestriction::SOFTAP) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP; + } + if (restrictions & CoexRestriction::WIFI_AWARE) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE; + } + auto legacy_status = + legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCountryCodeInternal(const std::array<int8_t, 2>& code) { + auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<V1_5::WifiUsableChannel>> WifiChip::getUsableChannelsInternal( + WifiBand /*band*/, uint32_t /*ifaceModeMask*/, uint32_t /*filterMask*/) { + LOG(ERROR) << "getUsableChannels is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiChip::triggerSubsystemRestartInternal() { + auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart(); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, sp<V1_6::IWifiRttController>> WifiChip::createRttControllerInternal_1_6( + const sp<IWifiIface>& bound_iface) { + if (sta_ifaces_.size() == 0 && + !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) { + LOG(ERROR) << "createRttControllerInternal_1_6: Chip cannot support STAs " + "(and RTT by extension)"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + sp<WifiRttController> rtt = + new WifiRttController(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_); + rtt_controllers_.emplace_back(rtt); + return {createWifiStatus(WifiStatusCode::SUCCESS), rtt}; +} + +std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> WifiChip::getUsableChannelsInternal_1_6( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask) { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels; + std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels( + hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band), + hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask), + hidl_struct_util::convertHidlUsableChannelFilterToLegacy(filterMask)); + + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<V1_6::WifiUsableChannel> hidl_usable_channels; + if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(legacy_usable_channels, + &hidl_usable_channels)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels}; +} + +std::pair<WifiStatus, V1_6::WifiRadioCombinationMatrix> +WifiChip::getSupportedRadioCombinationsMatrixInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_radio_combination_matrix* legacy_matrix; + + std::tie(legacy_status, legacy_matrix) = + legacy_hal_.lock()->getSupportedRadioCombinationsMatrix(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + + V1_6::WifiRadioCombinationMatrix hidl_matrix; + if (!hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, + &hidl_matrix)) { + LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToHidl() "; + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_matrix}; +} + +std::pair<WifiStatus, std::vector<V1_6::IWifiChip::ChipMode>> +WifiChip::getAvailableModesInternal_1_6() { + return {createWifiStatus(WifiStatusCode::SUCCESS), modes_}; +} + +WifiStatus WifiChip::handleChipConfiguration( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, 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. + if (isValidModeId(current_mode_id_)) { + LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id; + invalidateAndRemoveAllIfaces(); + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {}); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + } + // Firmware mode change not needed for V2 devices. + bool success = true; + if (mode_id == feature_flags::chip_mode_ids::kV1Sta) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); + } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) { + 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); + } + // Every time the HAL is restarted, we need to register the + // radio mode change callback. + WifiStatus status = registerRadioModeChangeCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + // This probably is not a critical failure? + LOG(ERROR) << "Failed to register radio mode change callback"; + } + // Extract and save the version information into property. + std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> version_info; + version_info = WifiChip::requestChipDebugInfoInternal(); + if (WifiStatusCode::SUCCESS == version_info.first.code) { + property_set("vendor.wlan.firmware.version", + version_info.second.firmwareDescription.c_str()); + property_set("vendor.wlan.driver.version", version_info.second.driverDescription.c_str()); + } + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::registerDebugRingBufferCallback() { + if (debug_ring_buffer_cb_registered_) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } + + android::wp<WifiChip> weak_ptr_this(this); + const auto& on_ring_buffer_data_callback = + [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& 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; + Ringbuffer::AppendStatus appendstatus; + if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(status, + &hidl_status)) { + LOG(ERROR) << "Error converting ring buffer status"; + return; + } + { + std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t); + const auto& target = shared_ptr_this->ringbuffer_map_.find(name); + if (target != shared_ptr_this->ringbuffer_map_.end()) { + Ringbuffer& cur_buffer = target->second; + appendstatus = cur_buffer.append(data); + } else { + LOG(ERROR) << "Ringname " << name << " not found"; + return; + } + // unique_lock unlocked here + } + if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) { + LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer"; + shared_ptr_this->writeRingbufferFilesInternal(); + return; + } + + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler( + getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback); + + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = true; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerRadioModeChangeCallback() { + android::wp<WifiChip> weak_ptr_this(this); + const auto& on_radio_mode_change_callback = + [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) { + 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<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos; + if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(mac_infos, + &hidl_radio_mode_infos)) { + LOG(ERROR) << "Error converting wifi mac info"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos).isOk()) { + LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4" + << " callback on: " << toString(callback); + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->registerRadioModeChangeCallbackHandler( + getFirstActiveWlanIfaceName(), on_radio_mode_change_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::vector<V1_6::IWifiChip::ChipConcurrencyCombination> +WifiChip::getCurrentModeConcurrencyCombinations() { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return {}; + } + for (const auto& mode : modes_) { + if (mode.id == current_mode_id_) { + return mode.availableCombinations; + } + } + CHECK(0) << "Expected to find concurrency combinations for current mode!"; + return {}; +} + +// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently +// created of the corresponding concurrency type. +std::map<IfaceConcurrencyType, size_t> WifiChip::getCurrentConcurrencyCombination() { + std::map<IfaceConcurrencyType, size_t> iface_counts; + uint32_t num_ap = 0; + uint32_t num_ap_bridged = 0; + for (const auto& ap_iface : ap_ifaces_) { + std::string ap_iface_name = ap_iface->getName(); + if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 && + br_ifaces_ap_instances_[ap_iface_name].size() > 1) { + num_ap_bridged++; + } else { + num_ap++; + } + } + iface_counts[IfaceConcurrencyType::AP] = num_ap; + iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged; + iface_counts[IfaceConcurrencyType::NAN] = nan_ifaces_.size(); + iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size(); + iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size(); + return iface_counts; +} + +// This expands the provided concurrency combinations to a more parseable +// form. Returns a vector of available combinations possible with the number +// of each concurrency type in the combination. +// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework. +std::vector<std::map<IfaceConcurrencyType, size_t>> WifiChip::expandConcurrencyCombinations( + const V1_6::IWifiChip::ChipConcurrencyCombination& combination) { + uint32_t num_expanded_combos = 1; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + num_expanded_combos *= limit.types.size(); + } + } + + // Allocate the vector of expanded combos and reset all concurrency type counts to 0 + // in each combo. + std::vector<std::map<IfaceConcurrencyType, size_t>> expanded_combos; + expanded_combos.resize(num_expanded_combos); + for (auto& expanded_combo : expanded_combos) { + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + expanded_combo[type] = 0; + } + } + uint32_t span = num_expanded_combos; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + span /= limit.types.size(); + for (uint32_t k = 0; k < num_expanded_combos; ++k) { + const auto iface_type = limit.types[(k / span) % limit.types.size()]; + expanded_combos[k][iface_type]++; + } + } + } + return expanded_combos; +} + +bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes( + const std::map<IfaceConcurrencyType, size_t>& expanded_combo, + IfaceConcurrencyType requested_type) { + const auto current_combo = getCurrentConcurrencyCombination(); + + // Check if we have space for 1 more iface of |type| in this combo + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + size_t num_ifaces_needed = current_combo.at(type); + if (type == requested_type) { + num_ifaces_needed++; + } + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} + +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency type can be added to the current mode +// with the concurrency combination that is already active. +bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes( + IfaceConcurrencyType requested_type) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeConcurrencyCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandConcurrencyCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo, + requested_type)) { + return true; + } + } + } + return false; +} + +// Note: This does not consider concurrency types already active. It only checks if the +// provided expanded concurrency combination can support the requested combo. +bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo( + const std::map<IfaceConcurrencyType, size_t>& expanded_combo, + const std::map<IfaceConcurrencyType, size_t>& req_combo) { + // Check if we have space for 1 more |type| in this combo + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + if (req_combo.count(type) == 0) { + // Concurrency type not in the req_combo. + continue; + } + size_t num_ifaces_needed = req_combo.at(type); + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency combo can be added to the current mode. +// Note: This does not consider concurrency types already active. It only checks if the +// current mode can support the requested combo. +bool WifiChip::canCurrentModeSupportConcurrencyCombo( + const std::map<IfaceConcurrencyType, size_t>& req_combo) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeConcurrencyCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandConcurrencyCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) { + return true; + } + } + } + return false; +} + +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency type can be added to the current mode. +bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) { + // Check if we can support at least 1 of the requested concurrency type. + std::map<IfaceConcurrencyType, size_t> req_iface_combo; + req_iface_combo[requested_type] = 1; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +bool WifiChip::isValidModeId(ChipModeId mode_id) { + for (const auto& mode : modes_) { + if (mode.id == mode_id) { + return true; + } + } + return false; +} + +bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { + // Check if we can support at least 1 STA & 1 AP concurrently. + std::map<IfaceConcurrencyType, size_t> req_iface_combo; + req_iface_combo[IfaceConcurrencyType::STA] = 1; + req_iface_combo[IfaceConcurrencyType::AP] = 1; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() { + // Check if we can support at least 2 STA concurrently. + std::map<IfaceConcurrencyType, size_t> req_iface_combo; + req_iface_combo[IfaceConcurrencyType::STA] = 2; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +std::string WifiChip::getFirstActiveWlanIfaceName() { + if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); + if (ap_ifaces_.size() > 0) { + // If the first active wlan iface is bridged iface. + // Return first instance name. + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ap_ifaces_[0]->getName()) { + return it.second[0]; + } + } + return ap_ifaces_[0]->getName(); + } + // This could happen if the chip call is made before any STA/AP + // iface is created. Default to wlan0 for such cases. + LOG(WARNING) << "No active wlan interfaces in use! Using default"; + return getWlanIfaceNameWithType(IfaceType::STA, 0); +} + +// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| +// not already in use. +// Note: This doesn't check the actual presence of these interfaces. +std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) { + for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) { + const auto ifname = getWlanIfaceNameWithType(type, idx); + if (findUsingNameFromBridgedApInstances(ifname)) continue; + if (findUsingName(ap_ifaces_, ifname)) continue; + if (findUsingName(sta_ifaces_, ifname)) continue; + return ifname; + } + // This should never happen. We screwed up somewhere if it did. + CHECK(false) << "All wlan interfaces in use already!"; + return {}; +} + +uint32_t WifiChip::startIdxOfApIface() { + if (isDualStaConcurrencyAllowedInCurrentMode()) { + // When the HAL support dual STAs, AP should start with idx 2. + return 2; + } else if (isStaApConcurrencyAllowedInCurrentMode()) { + // When the HAL support STA + AP but it doesn't support dual STAs. + // AP should start with idx 1. + return 1; + } + // No concurrency support. + return 0; +} + +// AP iface names start with idx 1 for modes supporting +// concurrent STA, else start with idx 0. +std::string WifiChip::allocateApIfaceName() { + // Check if we have a dedicated iface for AP. + std::vector<std::string> ifnames = getPredefinedApIfaceNames(true); + for (auto const& ifname : ifnames) { + if (findUsingName(ap_ifaces_, ifname)) continue; + return ifname; + } + return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface()); +} + +std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() { + // Check if we have a dedicated iface for AP. + std::vector<std::string> instances = getPredefinedApIfaceNames(true); + if (instances.size() == 2) { + return instances; + } else { + int num_ifaces_need_to_allocate = 2 - instances.size(); + for (int i = 0; i < num_ifaces_need_to_allocate; i++) { + std::string instance_name = + allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i); + if (!instance_name.empty()) { + instances.push_back(instance_name); + } + } + } + return instances; +} + +// STA iface names start with idx 0. +// Primary STA iface will always be 0. +std::string WifiChip::allocateStaIfaceName() { + return allocateApOrStaIfaceName(IfaceType::STA, 0); +} + +bool WifiChip::writeRingbufferFilesInternal() { + if (!removeOldFilesInternal()) { + LOG(ERROR) << "Error occurred while deleting old tombstone files"; + return false; + } + // write ringbuffers to file + { + std::unique_lock<std::mutex> lk(lock_t); + for (auto& item : ringbuffer_map_) { + Ringbuffer& cur_buffer = item.second; + if (cur_buffer.getData().empty()) { + continue; + } + const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX"; + const int dump_fd = mkstemp(makeCharVec(file_path_raw).data()); + if (dump_fd == -1) { + PLOG(ERROR) << "create file failed"; + return false; + } + unique_fd file_auto_closer(dump_fd); + for (const auto& cur_block : cur_buffer.getData()) { + if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) { + PLOG(ERROR) << "Ring buffer: " << item.first + << " is corrupted. Invalid block size: " << cur_block.size(); + break; + } + if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) == + -1) { + PLOG(ERROR) << "Error writing to file"; + } + } + cur_buffer.clear(); + } + // unique_lock unlocked here + } + return true; +} + +std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) { + std::string ifname; + + // let the legacy hal override the interface name + legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname); + if (err == legacy_hal::WIFI_SUCCESS) return ifname; + + return getWlanIfaceName(idx); +} + +void WifiChip::invalidateAndClearBridgedApAll() { + for (auto const& it : br_ifaces_ap_instances_) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(it.first, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(it.first); + } + br_ifaces_ap_instances_.clear(); +} + +void WifiChip::deleteApIface(const std::string& if_name) { + if (if_name.empty()) return; + // delete bridged interfaces if have + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == if_name) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(if_name, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(if_name); + br_ifaces_ap_instances_.erase(if_name); + // ifname is bridged AP, return here. + return; + } + } + + // No bridged AP case, delete AP iface + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(if_name); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << if_name << " " + << legacyErrorToString(legacy_status); + } +} + +bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) { + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == name) { + return true; + } + for (auto const& iface : it.second) { + if (iface == name) { + return true; + } + } + } + return false; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h new file mode 100644 index 0000000..27baf3d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h @@ -0,0 +1,322 @@ +/* + * 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_ + +// HACK: NAN is a macro defined in math.h, which can be included in various +// headers. This wifi HAL uses an enum called NAN, which does not compile when +// the macro is defined. Undefine NAN to work around it. +#undef NAN + +#include <list> +#include <map> +#include <mutex> + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.6/IWifiChip.h> +#include <android/hardware/wifi/1.6/IWifiRttController.h> +#include <android/hardware/wifi/1.6/IWifiStaIface.h> + +#include "hidl_callback_util.h" +#include "ringbuffer.h" +#include "wifi_ap_iface.h" +#include "wifi_feature_flags.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_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; +using V1_5::WifiBand; + +/** + * 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_6::IWifiChip { + public: + WifiChip(ChipId chip_id, bool is_primary, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<mode_controller::WifiModeController> mode_controller, + const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags, + const std::function<void(const std::string&)>& subsystemCallbackHandler); + // 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<sp<V1_4::IWifiChipEventCallback>> getEventCallbacks(); + + // HIDL methods exposed. + Return<void> getId(getId_cb hidl_status_cb) override; + // Deprecated support for this callback + Return<void> registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> getAvailableModes(getAvailableModes_cb hidl_status_cb) override; + Return<void> configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) override; + Return<void> getMode(getMode_cb hidl_status_cb) override; + Return<void> requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) override; + Return<void> requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) override; + Return<void> requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) override; + Return<void> createApIface(createApIface_cb hidl_status_cb) override; + Return<void> createBridgedApIface(createBridgedApIface_cb hidl_status_cb) override; + Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; + Return<void> getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override; + Return<void> removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override; + Return<void> removeIfaceInstanceFromBridgedApIface( + const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override; + Return<void> createNanIface(createNanIface_cb hidl_status_cb) override; + Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; + Return<void> getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) override; + Return<void> removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) override; + Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override; + Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override; + Return<void> getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) override; + Return<void> removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) override; + Return<void> createStaIface(createStaIface_cb hidl_status_cb) override; + Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override; + Return<void> getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) override; + Return<void> removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) override; + Return<void> createRttController(const sp<IWifiIface>& bound_iface, + createRttController_cb hidl_status_cb) override; + Return<void> getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) override; + Return<void> 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<void> forceDumpToDebugRingBuffer(const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) override; + Return<void> flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) override; + Return<void> stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return<void> getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) override; + Return<void> enableDebugErrorAlerts(bool enable, + enableDebugErrorAlerts_cb hidl_status_cb) override; + Return<void> selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return<void> resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) override; + Return<void> setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiChipEventCallback>& event_callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return<void> selectTxPowerScenario_1_2(TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return<void> getCapabilities_1_3(getCapabilities_cb hidl_status_cb) override; + Return<void> getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) override; + Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override; + Return<void> createRttController_1_4(const sp<IWifiIface>& bound_iface, + createRttController_1_4_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_4(const sp<V1_4::IWifiChipEventCallback>& event_callback, + registerEventCallback_1_4_cb hidl_status_cb) override; + Return<void> setMultiStaPrimaryConnection( + const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) override; + Return<void> setMultiStaUseCase(MultiStaUseCase use_case, + setMultiStaUseCase_cb hidl_status_cb) override; + Return<void> setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafe_channels, + hidl_bitfield<IfaceType> restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) override; + Return<void> setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb _hidl_cb) override; + Return<void> getUsableChannels(WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask, + hidl_bitfield<V1_5::IWifiChip::UsableChannelFilter> filterMask, + getUsableChannels_cb _hidl_cb) override; + Return<void> triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) override; + Return<void> createRttController_1_6(const sp<IWifiIface>& bound_iface, + createRttController_1_6_cb hidl_status_cb) override; + Return<void> getUsableChannels_1_6(WifiBand band, + hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask, + hidl_bitfield<UsableChannelFilter> filterMask, + getUsableChannels_1_6_cb _hidl_cb) override; + Return<void> getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override; + Return<void> getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) override; + + private: + void invalidateAndRemoveAllIfaces(); + // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are + // invalidated & removed. + void invalidateAndRemoveDependencies(const std::string& removed_iface_name); + + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, ChipId> getIdInternal(); + // Deprecated support for this callback + WifiStatus registerEventCallbackInternal( + const sp<V1_0::IWifiChipEventCallback>& event_callback); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal(); + std::pair<WifiStatus, std::vector<V1_0::IWifiChip::ChipMode>> getAvailableModesInternal(); + WifiStatus configureChipInternal(std::unique_lock<std::recursive_mutex>* lock, + ChipModeId mode_id); + std::pair<WifiStatus, uint32_t> getModeInternal(); + std::pair<WifiStatus, IWifiChip::ChipDebugInfo> requestChipDebugInfoInternal(); + std::pair<WifiStatus, std::vector<uint8_t>> requestDriverDebugDumpInternal(); + std::pair<WifiStatus, std::vector<uint8_t>> requestFirmwareDebugDumpInternal(); + sp<WifiApIface> newWifiApIface(std::string& ifname); + WifiStatus createVirtualApInterface(const std::string& apVirtIf); + std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createApIfaceInternal(); + std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createBridgedApIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal(); + std::pair<WifiStatus, sp<V1_5::IWifiApIface>> getApIfaceInternal(const std::string& ifname); + WifiStatus removeApIfaceInternal(const std::string& ifname); + WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(const std::string& brIfaceName, + const std::string& ifInstanceName); + std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal(); + std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(const std::string& ifname); + WifiStatus removeNanIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal(); + std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(const std::string& ifname); + WifiStatus removeP2pIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> createStaIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal(); + std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> getStaIfaceInternal(const std::string& ifname); + WifiStatus removeStaIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<V1_0::IWifiRttController>> createRttControllerInternal( + const sp<IWifiIface>& bound_iface); + std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>> + 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 flushRingBufferToFileInternal(); + WifiStatus stopLoggingToDebugRingBufferInternal(); + std::pair<WifiStatus, WifiDebugHostWakeReasonStats> getDebugHostWakeReasonStatsInternal(); + WifiStatus enableDebugErrorAlertsInternal(bool enable); + WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario); + WifiStatus resetTxPowerScenarioInternal(); + WifiStatus setLatencyModeInternal(LatencyMode mode); + WifiStatus registerEventCallbackInternal_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback); + WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3(); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_5(); + std::pair<WifiStatus, sp<V1_4::IWifiRttController>> createRttControllerInternal_1_4( + const sp<IWifiIface>& bound_iface); + WifiStatus registerEventCallbackInternal_1_4( + const sp<V1_4::IWifiChipEventCallback>& event_callback); + WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname); + WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case); + WifiStatus setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels, + uint32_t restrictions); + WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code); + std::pair<WifiStatus, std::vector<V1_5::WifiUsableChannel>> getUsableChannelsInternal( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask); + WifiStatus handleChipConfiguration(std::unique_lock<std::recursive_mutex>* lock, + ChipModeId mode_id); + WifiStatus registerDebugRingBufferCallback(); + WifiStatus registerRadioModeChangeCallback(); + std::vector<V1_6::IWifiChip::ChipConcurrencyCombination> + getCurrentModeConcurrencyCombinations(); + std::map<IfaceConcurrencyType, size_t> getCurrentConcurrencyCombination(); + std::vector<std::map<IfaceConcurrencyType, size_t>> expandConcurrencyCombinations( + const V1_6::IWifiChip::ChipConcurrencyCombination& combination); + bool canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes( + const std::map<IfaceConcurrencyType, size_t>& expanded_combo, + IfaceConcurrencyType requested_type); + bool canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType requested_type); + bool canExpandedConcurrencyComboSupportConcurrencyCombo( + const std::map<IfaceConcurrencyType, size_t>& expanded_combo, + const std::map<IfaceConcurrencyType, size_t>& req_combo); + bool canCurrentModeSupportConcurrencyCombo( + const std::map<IfaceConcurrencyType, size_t>& req_combo); + bool canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type); + bool isValidModeId(ChipModeId mode_id); + bool isStaApConcurrencyAllowedInCurrentMode(); + bool isDualStaConcurrencyAllowedInCurrentMode(); + uint32_t startIdxOfApIface(); + std::string getFirstActiveWlanIfaceName(); + std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx); + std::string allocateApIfaceName(); + std::vector<std::string> allocateBridgedApInstanceNames(); + std::string allocateStaIfaceName(); + bool writeRingbufferFilesInternal(); + std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx); + void invalidateAndClearBridgedApAll(); + void deleteApIface(const std::string& if_name); + bool findUsingNameFromBridgedApInstances(const std::string& name); + WifiStatus triggerSubsystemRestartInternal(); + void QcRemoveAndClearDynamicIfaces(); + std::pair<WifiStatus, sp<V1_6::IWifiRttController>> createRttControllerInternal_1_6( + const sp<IWifiIface>& bound_iface); + std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> getUsableChannelsInternal_1_6( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask); + std::pair<WifiStatus, WifiRadioCombinationMatrix> getSupportedRadioCombinationsMatrixInternal(); + std::pair<WifiStatus, std::vector<V1_6::IWifiChip::ChipMode>> getAvailableModesInternal_1_6(); + + ChipId chip_id_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<mode_controller::WifiModeController> mode_controller_; + std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_; + std::vector<sp<WifiApIface>> ap_ifaces_; + std::vector<sp<WifiNanIface>> nan_ifaces_; + std::vector<sp<WifiP2pIface>> p2p_ifaces_; + std::vector<sp<WifiStaIface>> sta_ifaces_; + std::vector<sp<WifiRttController>> rtt_controllers_; + std::map<std::string, Ringbuffer> ringbuffer_map_; + bool is_valid_; + // Members pertaining to chip configuration. + uint32_t current_mode_id_; + std::mutex lock_t; + std::vector<V1_6::IWifiChip::ChipMode> modes_; + // 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<V1_4::IWifiChipEventCallback> event_cb_handler_; + + const std::function<void(const std::string&)> subsystemCallbackHandler_; + std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_; + + std::vector<sp<WifiApIface>> created_ap_ifaces_; + std::vector<sp<WifiStaIface>> created_sta_ifaces_; + + DISALLOW_COPY_AND_ASSIGN(WifiChip); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_CHIP_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp new file mode 100644 index 0000000..e80a3cd --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp @@ -0,0 +1,247 @@ +/* + * 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 <string> + +#include <android-base/logging.h> +#include <cutils/properties.h> + +#include "wifi_feature_flags.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace feature_flags { + +using V1_0::ChipModeId; +using V1_0::IWifiChip; +using V1_6::IfaceConcurrencyType; + +/* The chip may either have a single mode supporting any number of combinations, + * or a fixed dual-mode (so it involves firmware loading to switch between + * modes) setting. If there is a need to support more modes, it needs to be + * implemented manually in WiFi HAL (see changeFirmwareMode in + * WifiChip::handleChipConfiguration). + * + * Supported combinations are defined in device's makefile, for example: + * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}}, + * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}} + * What means: + * Interface concurrency combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface + * operations. + * Interface concurrency combination 2: 1 STA and 2 AP concurrent iface operations. + * + * For backward compatibility, the following makefile flags can be used to + * generate combinations list: + * - WIFI_HIDL_FEATURE_DUAL_INTERFACE + * - WIFI_HIDL_FEATURE_DISABLE_AP + * - WIFI_HIDL_FEATURE_AWARE + * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided. + * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with + * two concurrency combinations: + * Interface Concurrency Combination 1: Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Interface Concurrency Combination 2: Will support 1 STA and 1 AP concurrent + * iface operations. + * + * The only dual-mode configuration supported is for alternating STA and AP + * mode, that may involve firmware reloading. In such case, there are 2 separate + * modes of operation with 1 concurrency combination each: + * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Mode 2 (AP mode): Will support 1 AP iface operation. + * + * If Aware is enabled, the concurrency combination will be modified to support either + * P2P or NAN in place of just P2P. + */ +// clang-format off +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE) +// former V2 (fixed dual interface) setup expressed as V3 +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +# ifdef WIFI_HIDL_FEATURE_DISABLE_AP +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif +# else +# ifdef WIFI_HIDL_FEATURE_AWARE +// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// (1 STA + 1 AP) or (1 STA + 1 P2P) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P}, 1}} +# endif +# endif +#else +// V1 (fixed single interface, dual-mode chip) +constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta; +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif + +# ifndef WIFI_HIDL_FEATURE_DISABLE_AP +# define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}} +# endif +#endif +// clang-format on + +/** + * Helper class to convert a collection of combination limits to a combination. + * + * The main point here is to simplify the syntax required by + * WIFI_HAL_INTERFACE_COMBINATIONS. + */ +struct ChipConcurrencyCombination + : public hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombinationLimit> { + ChipConcurrencyCombination( + const std::initializer_list<V1_6::IWifiChip::ChipConcurrencyCombinationLimit> list) + : hidl_vec(list) {} + + operator V1_6::IWifiChip::ChipConcurrencyCombination() const { return {*this}; } + + static hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombination> make_vec( + const std::initializer_list<ChipConcurrencyCombination> list) { + return hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombination>( // + std::begin(list), std::end(list)); + } +}; + +#define STA IfaceConcurrencyType::STA +#define AP IfaceConcurrencyType::AP +#define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED +#define P2P IfaceConcurrencyType::P2P +#define NAN IfaceConcurrencyType::NAN +static const std::vector<V1_6::IWifiChip::ChipMode> kChipModesPrimary{ + {kMainModeId, ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})}, +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP + {chip_mode_ids::kV1Ap, + ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})}, +#endif +}; + +static const std::vector<V1_6::IWifiChip::ChipMode> kChipModesSecondary{ +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP + {chip_mode_ids::kV3, + ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})}, +#endif +}; + +constexpr char kDebugPresetInterfaceCombinationIdxProperty[] = + "persist.vendor.debug.wifi.hal.preset_interface_combination_idx"; +// List of pre-defined concurrency combinations that can be enabled at runtime via +// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the +// corresponding index value. +static const std::vector<std::pair<std::string, std::vector<V1_6::IWifiChip::ChipMode>>> + kDebugChipModes{// Legacy combination - No STA/AP concurrencies. + // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN)) + {"No STA/AP Concurrency", + {{kMainModeId, ChipConcurrencyCombination::make_vec( + {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + AP concurrency + // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) + {"STA + AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency + // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}, + + // AP + AP + STA concurrency + // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN)) + {"Dual AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency and AP + AP + STA concurrency + // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA & Dual AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency + // 5 - (1 STA + 1 AP (bridged or single) | P2P | NAN), or (2 STA)) + {"Dual STA or STA plus single other interface", + {{kMainModeId, ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{P2P, NAN, AP, AP_BRIDGED}, 1}}, + {{{STA}, 2}}})}}}}; + +#undef STA +#undef AP +#undef P2P +#undef NAN + +#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +#pragma message \ + "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \ + "'config_wifi_ap_randomization_supported' in " \ + "frameworks/base/core/res/res/values/config.xml in the device overlay " \ + "instead" +#endif // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION + +WifiFeatureFlags::WifiFeatureFlags() {} + +std::vector<V1_6::IWifiChip::ChipMode> WifiFeatureFlags::getChipModesForPrimary() { + std::array<char, PROPERTY_VALUE_MAX> buffer; + auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, buffer.data(), nullptr); + // Debug property not set, use the device preset concurrency combination. + if (res <= 0) return kChipModesPrimary; + + // Debug property set, use one of the debug preset concurrency combination. + unsigned long idx = std::stoul(buffer.data()); + if (idx >= kDebugChipModes.size()) { + LOG(ERROR) << "Invalid index set in property: " + << kDebugPresetInterfaceCombinationIdxProperty; + return kChipModesPrimary; + } + std::string name; + std::vector<V1_6::IWifiChip::ChipMode> chip_modes; + std::tie(name, chip_modes) = kDebugChipModes[idx]; + LOG(INFO) << "Using debug chip mode: <" << name + << "> set via property: " << kDebugPresetInterfaceCombinationIdxProperty; + return chip_modes; +} + +std::vector<V1_6::IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(bool is_primary) { + return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary; +} + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h new file mode 100644 index 0000000..1635341 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h @@ -0,0 +1,58 @@ +/* + * 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_ + +#include <android/hardware/wifi/1.6/IWifiChip.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace feature_flags { + +namespace chip_mode_ids { +// These mode ID's should be unique (even across combo versions). Refer to +// handleChipConfiguration() for it's usage. +constexpr V1_0::ChipModeId kInvalid = UINT32_MAX; +// Mode ID's for V1 +constexpr V1_0::ChipModeId kV1Sta = 0; +constexpr V1_0::ChipModeId kV1Ap = 1; +// Mode ID for V3 +constexpr V1_0::ChipModeId kV3 = 3; +} // namespace chip_mode_ids + +class WifiFeatureFlags { + public: + WifiFeatureFlags(); + virtual ~WifiFeatureFlags() = default; + + virtual std::vector<V1_6::IWifiChip::ChipMode> getChipModes(bool is_primary); + + private: + std::vector<V1_6::IWifiChip::ChipMode> getChipModesForPrimary(); +}; + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_FEATURE_FLAGS_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp new file mode 100644 index 0000000..d55e4f8 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019 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 <net/if.h> +#include <cstddef> +#include <iostream> +#include <limits> +#include <random> + +#include <android-base/logging.h> +#include <android-base/macros.h> +#include <private/android_filesystem_config.h> + +#undef NAN +#include "wifi_iface_util.h" + +namespace { +// Constants to set the local bit & clear the multicast bit. +constexpr uint8_t kMacAddressMulticastMask = 0x01; +constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace iface_util { + +WifiIfaceUtil::WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal) + : iface_tool_(iface_tool), + legacy_hal_(legacy_hal), + random_mac_address_(nullptr), + event_handlers_map_() {} + +std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(const std::string& iface_name) { + return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str()); +} + +bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, + const std::array<uint8_t, 6>& mac) { +#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(iface_name); + + if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) && + !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) { + LOG(ERROR) << "SetUpState(false) failed."; + return false; + } +#endif + bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac); +#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE + if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) && + !iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready."; + // Wait for driver ready and try to set iface UP again + if (legacy_hal_.lock()->waitForDriverReady() != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "SetUpState(true) wait for driver ready failed."; + return false; + } + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed after retry."; + return false; + } + } +#endif + IfaceEventHandlers event_handlers = {}; + const auto it = event_handlers_map_.find(iface_name); + if (it != event_handlers_map_.end()) { + event_handlers = it->second; + } + if (event_handlers.on_state_toggle_off_on != nullptr) { + event_handlers.on_state_toggle_off_on(iface_name); + } + if (!success) { + LOG(ERROR) << "SetMacAddress failed on " << iface_name; + } else { + LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name; + } + return success; +} + +std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() { + if (random_mac_address_) { + return *random_mac_address_.get(); + } + random_mac_address_ = std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress()); + return *random_mac_address_.get(); +} + +void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers) { + event_handlers_map_[iface_name] = handlers; +} + +void WifiIfaceUtil::unregisterIfaceEventHandlers(const std::string& iface_name) { + event_handlers_map_.erase(iface_name); +} + +std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() { + std::array<uint8_t, 6> address = {}; + std::random_device rd; + std::default_random_engine engine(rd()); + std::uniform_int_distribution<uint8_t> dist(std::numeric_limits<uint8_t>::min(), + std::numeric_limits<uint8_t>::max()); + for (size_t i = 0; i < address.size(); i++) { + address[i] = dist(engine); + } + // Set the local bit and clear the multicast bit. + address[0] |= kMacAddressLocallyAssignedMask; + address[0] &= ~kMacAddressMulticastMask; + return address; +} + +bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) { + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) { + LOG(ERROR) << "SetUpState to " << request_up << " failed"; + return false; + } + return true; +} + +unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) { + return if_nametoindex(iface_name.c_str()); +} + +bool WifiIfaceUtil::createBridge(const std::string& br_name) { + if (!iface_tool_.lock()->createBridge(br_name)) { + return false; + } + + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), true)) { + LOG(ERROR) << "bridge SetUpState(true) failed."; + } + return true; +} + +bool WifiIfaceUtil::deleteBridge(const std::string& br_name) { + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), false)) { + LOG(INFO) << "SetUpState(false) failed for bridge=" << br_name.c_str(); + } + + return iface_tool_.lock()->deleteBridge(br_name); +} + +bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, const std::string& if_name) { + return iface_tool_.lock()->addIfaceToBridge(br_name, if_name); +} + +bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) { + return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name); +} + +} // namespace iface_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h new file mode 100644 index 0000000..c5db5de --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 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_IFACE_UTIL_H_ +#define WIFI_IFACE_UTIL_H_ + +#include <wifi_system/interface_tool.h> + +#include <android/hardware/wifi/1.0/IWifi.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace iface_util { + +// Iface event handlers. +struct IfaceEventHandlers { + // Callback to be invoked when the iface is set down & up for MAC address + // change. + std::function<void(const std::string& iface_name)> on_state_toggle_off_on; +}; + +/** + * Util class for common iface operations. + */ +class WifiIfaceUtil { + public: + WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal); + virtual ~WifiIfaceUtil() = default; + + virtual std::array<uint8_t, 6> getFactoryMacAddress(const std::string& iface_name); + virtual bool setMacAddress(const std::string& iface_name, const std::array<uint8_t, 6>& mac); + // Get or create a random MAC address. The MAC address returned from + // this method will remain the same throughout the lifetime of the HAL + // daemon. (So, changes on every reboot) + virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress(); + + // Register for any iface event callbacks for the provided interface. + virtual void registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers); + virtual void unregisterIfaceEventHandlers(const std::string& iface_name); + virtual bool setUpState(const std::string& iface_name, bool request_up); + virtual unsigned ifNameToIndex(const std::string& iface_name); + + virtual bool createBridge(const std::string& br_name); + + virtual bool deleteBridge(const std::string& br_name); + + virtual bool addIfaceToBridge(const std::string& br_name, const std::string& if_name); + + virtual bool removeIfaceFromBridge(const std::string& br_name, const std::string& if_name); + // Get a random MAC address. + virtual std::array<uint8_t, 6> createRandomMacAddress(); + + private: + std::weak_ptr<wifi_system::InterfaceTool> iface_tool_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_; + std::map<std::string, IfaceEventHandlers> event_handlers_map_; +}; + +} // namespace iface_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_IFACE_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp new file mode 100644 index 0000000..43cb7c4 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp @@ -0,0 +1,1654 @@ +/* + * 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 <array> +#include <chrono> + +#include <android-base/logging.h> +#include <cutils/properties.h> +#include <net/if.h> + +#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; +static constexpr uint32_t kMaxWifiUsableChannels = 256; +static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256; +// need a long timeout (1000ms) for chips that unload their driver. +static constexpr uint32_t kMaxStopCompleteWaitMs = 1000; +static constexpr char kDriverPropName[] = "wlan.driver.status"; + +// Helper function to create a non-const char* for legacy Hal API's. +std::vector<char> makeCharVec(const std::string& str) { + std::vector<char> 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_6 { +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<void(wifi_handle handle)> 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<void(char*, int)> 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<void(char*, int)> 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<void(wifi_request_id, wifi_scan_event)> 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<void(wifi_request_id, wifi_scan_result*, uint32_t)> + 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<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))> + 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<void((wifi_request_id, uint8_t*, int8_t))> + 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<void(char*, char*, int, wifi_ring_buffer_status*)> + 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<void(wifi_request_id, char*, int, int)> 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 radio mode change indication. +std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)> + on_radio_mode_change_internal_callback; +void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_radio_mode_change_internal_callback) { + on_radio_mode_change_internal_callback(id, num_macs, mac_infos); + } +} + +// Callback to be invoked to report subsystem restart +std::function<void(const char*)> on_subsystem_restart_internal_callback; +void onAsyncSubsystemRestart(const char* error) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_subsystem_restart_internal_callback) { + on_subsystem_restart_internal_callback(error); + } +} + +// Callback to be invoked for rtt results results. +std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])> + 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<void(transaction_id, const NanResponseMsg&)> 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<void(const NanPublishRepliedInd&)> on_nan_event_publish_replied_user_callback; +void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) { + LOG(ERROR) << "onAysncNanEventPublishReplied triggered"; +} + +std::function<void(const NanPublishTerminatedInd&)> 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<void(const NanMatchInd&)> 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<void(const NanMatchExpiredInd&)> 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<void(const NanSubscribeTerminatedInd&)> + 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<void(const NanFollowupInd&)> 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<void(const NanDiscEngEventInd&)> 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<void(const NanDisabledInd&)> 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<void(const NanTCAInd&)> 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<void(const NanBeaconSdfPayloadInd&)> 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<void(const NanDataPathRequestInd&)> 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<void(const NanDataPathConfirmInd&)> 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<void(const NanDataPathEndInd&)> 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<void(const NanTransmitFollowupInd&)> 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<void(const NanRangeRequestInd&)> 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<void(const NanRangeReportInd&)> 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); + } +} + +std::function<void(const NanDataPathScheduleUpdateInd&)> on_nan_event_schedule_update_user_callback; +void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_schedule_update_user_callback && event) { + on_nan_event_schedule_update_user_callback(*event); + } +} + +// Callbacks for the various TWT operations. +std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback; +void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_setup_response_callback && event) { + on_twt_event_setup_response_callback(*event); + } +} + +std::function<void(const TwtTeardownCompletion&)> on_twt_event_teardown_completion_callback; +void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_teardown_completion_callback && event) { + on_twt_event_teardown_completion_callback(*event); + } +} + +std::function<void(const TwtInfoFrameReceived&)> on_twt_event_info_frame_received_callback; +void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_info_frame_received_callback && event) { + on_twt_event_info_frame_received_callback(*event); + } +} + +std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback; +void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_device_notify_callback && event) { + on_twt_event_device_notify_callback(*event); + } +} + +// Callback to report current CHRE NAN state +std::function<void(chre_nan_rtt_state)> on_chre_nan_rtt_internal_callback; +void onAsyncChreNanRttState(chre_nan_rtt_state state) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_chre_nan_rtt_internal_callback) { + on_chre_nan_rtt_internal_callback(state); + } +} + +// Callback to report cached scan results +std::function<void(wifi_cached_scan_report*)> on_cached_scan_results_internal_callback; +void onSyncCachedScanResults(wifi_cached_scan_report* cache_report) { + if (on_cached_scan_results_internal_callback) { + on_cached_scan_results_internal_callback(cache_report); + } +} + +// End of the free-standing "C" style callbacks. + +WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, + const wifi_hal_fn& fn, bool is_primary) + : global_func_table_(fn), + global_handle_(nullptr), + awaiting_event_loop_termination_(false), + is_started_(false), + iface_tool_(iface_tool), + is_primary_(is_primary) {} + +wifi_error WifiLegacyHal::initialize() { + LOG(DEBUG) << "Initialize legacy HAL"; + // this now does nothing, since HAL function table is provided + // to the constructor + return WIFI_SUCCESS; +} + +wifi_error WifiLegacyHal::start() { + // Ensure that we're starting in a good state. + CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() && + !awaiting_event_loop_termination_); + if (is_started_) { + LOG(DEBUG) << "Legacy HAL already started"; + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Waiting for the driver ready"; + wifi_error status = global_func_table_.wifi_wait_for_driver_ready(); + if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) { + LOG(ERROR) << "Failed or timed out awaiting driver ready"; + return status; + } + + if (is_primary_) { + property_set(kDriverPropName, "ok"); + + if (!iface_tool_.lock()->SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } + } + + LOG(DEBUG) << "Starting legacy HAL"; + 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 = retrieveIfaceHandles(); + if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) { + 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( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, + const std::function<void()>& 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"; + LOG(INFO) << "Legacy HAL stop complete callback received"; + // Invalidate all the internal pointers now that the HAL is + // stopped. + invalidate(); + if (is_primary_) iface_tool_.lock()->SetWifiUpState(false); + on_stop_complete_user_callback(); + is_started_ = false; + }; + awaiting_event_loop_termination_ = true; + global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete); + const auto status = + stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs), + [this] { return !awaiting_event_loop_termination_; }); + if (!status) { + LOG(ERROR) << "Legacy HAL stop failed or timed out"; + return WIFI_ERROR_UNKNOWN; + } + LOG(DEBUG) << "Legacy HAL stop complete"; + return WIFI_SUCCESS; +} + +bool WifiLegacyHal::isStarted() { + return is_started_; +} + +wifi_error WifiLegacyHal::waitForDriverReady() { + return global_func_table_.wifi_wait_for_driver_ready(); +} + +std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(const std::string& iface_name) { + std::array<char, kMaxVersionStringLength> buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name), + buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion( + const std::string& iface_name) { + std::array<char, kMaxVersionStringLength> buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name), + buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestDriverMemoryDump( + const std::string& iface_name) { + std::vector<uint8_t> driver_dump; + on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) { + driver_dump.insert(driver_dump.end(), reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name), + {onSyncDriverMemoryDump}); + on_driver_memory_dump_internal_callback = nullptr; + return {status, std::move(driver_dump)}; +} + +std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestFirmwareMemoryDump( + const std::string& iface_name) { + std::vector<uint8_t> firmware_dump; + on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) { + firmware_dump.insert(firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_firmware_memory_dump( + getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump}); + on_firmware_memory_dump_internal_callback = nullptr; + return {status, std::move(firmware_dump)}; +} + +std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet( + const std::string& iface_name) { + feature_set set = 0, chip_set = 0; + wifi_error status = WIFI_SUCCESS; + + static_assert(sizeof(set) == sizeof(uint64_t), + "Some feature_flags can not be represented in output"); + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + global_func_table_.wifi_get_chip_feature_set( + global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */ + + if (iface_handle) { + status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set); + } + return {status, static_cast<uint64_t>(set | chip_set)}; +} + +std::pair<wifi_error, PacketFilterCapabilities> WifiLegacyHal::getPacketFilterCapabilities( + const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + return {status, caps}; +} + +wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name, + const std::vector<uint8_t>& program) { + return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(), + program.size()); +} + +std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::readApfPacketFilterData( + const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + if (status != WIFI_SUCCESS) { + return {status, {}}; + } + + // Size the buffer to read the entire program & work memory. + std::vector<uint8_t> buffer(caps.max_len); + + status = global_func_table_.wifi_read_packet_filter( + getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size()); + return {status, std::move(buffer)}; +} + +std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities( + const std::string& iface_name) { + wifi_gscan_capabilities caps; + wifi_error status = + global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::startGscan( + const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params, + const std::function<void(wifi_request_id)>& 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 = [iface_name, 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<wifi_cached_scan_results> cached_scan_results; + std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name); + if (status == WIFI_SUCCESS) { + on_results_user_callback(id, cached_scan_results); + return; + } + FALLTHROUGH_INTENDED; + } + // 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, getIfaceHandle(iface_name), 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(const std::string& iface_name, 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, getIfaceHandle(iface_name)); + // 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<wifi_error, std::vector<uint32_t>> WifiLegacyHal::getValidFrequenciesForBand( + const std::string& iface_name, wifi_band band) { + static_assert(sizeof(uint32_t) >= sizeof(wifi_channel), + "Wifi Channel cannot be represented in output"); + std::vector<uint32_t> freqs; + freqs.resize(kMaxGscanFrequenciesForBand); + int32_t num_freqs = 0; + wifi_error status = global_func_table_.wifi_get_valid_channels( + getIfaceHandle(iface_name), band, freqs.size(), + reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs); + CHECK(num_freqs >= 0 && static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand); + freqs.resize(num_freqs); + return {status, std::move(freqs)}; +} + +wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) { + return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1); +} + +wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, 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(getIfaceHandle(iface_name), params); +} + +wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) { + // TODO: Do we care about these responses? + uint32_t clear_mask_rsp; + uint8_t stop_rsp; + return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF, + &clear_mask_rsp, 1, &stop_rsp); +} + +std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats( + const std::string& iface_name) { + 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) { + wifi_radio_stat* l_radio_stats_ptr; + wifi_peer_info* l_peer_info_stats_ptr; + + if (iface_stats_ptr != nullptr) { + link_stats_ptr->iface = *iface_stats_ptr; + l_peer_info_stats_ptr = iface_stats_ptr->peer_info; + for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) { + WifiPeerInfo peer; + peer.peer_info = *l_peer_info_stats_ptr; + if (l_peer_info_stats_ptr->num_rate > 0) { + /* Copy the rate stats */ + peer.rate_stats.assign( + l_peer_info_stats_ptr->rate_stats, + l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate); + } + peer.peer_info.num_rate = 0; + link_stats_ptr->peers.push_back(peer); + l_peer_info_stats_ptr = + (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) + + (sizeof(wifi_rate_stat) * + l_peer_info_stats_ptr->num_rate)); + } + 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; + } + l_radio_stats_ptr = radio_stats_ptr; + for (int i = 0; i < num_radios; i++) { + LinkLayerRadioStats radio; + + radio.stats = *l_radio_stats_ptr; + // Copy over the tx level array to the separate vector. + if (l_radio_stats_ptr->num_tx_levels > 0 && + l_radio_stats_ptr->tx_time_per_levels != nullptr) { + radio.tx_time_per_levels.assign( + l_radio_stats_ptr->tx_time_per_levels, + l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels); + } + radio.stats.num_tx_levels = 0; + radio.stats.tx_time_per_levels = nullptr; + /* Copy over the channel stat to separate vector */ + if (l_radio_stats_ptr->num_channels > 0) { + /* Copy the channel stats */ + radio.channel_stats.assign( + l_radio_stats_ptr->channels, + l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels); + } + link_stats_ptr->radios.push_back(radio); + l_radio_stats_ptr = + (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) + + (sizeof(wifi_channel_stat) * + l_radio_stats_ptr->num_channels)); + } + }; + + wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name), + {onSyncLinkLayerStatsResult}); + on_link_layer_stats_result_internal_callback = nullptr; + return {status, link_stats}; +} + +wifi_error WifiLegacyHal::startRssiMonitoring( + const std::string& iface_name, 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<uint8_t, 6> 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, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached}); + if (status != WIFI_SUCCESS) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, 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, getIfaceHandle(iface_name)); + // 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<wifi_error, wifi_roaming_capabilities> WifiLegacyHal::getRoamingCapabilities( + const std::string& iface_name) { + wifi_roaming_capabilities caps; + wifi_error status = + global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name, + const wifi_roaming_config& config) { + wifi_roaming_config config_internal = config; + return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal); +} + +wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name, + fw_roaming_state_t state) { + return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state); +} + +wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) { + return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable); +} + +wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name, + uint32_t cmd_id, uint16_t ether_type, + const std::vector<uint8_t>& ip_packet_data, + const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, + uint32_t period_in_ms) { + std::vector<uint8_t> ip_packet_data_internal(ip_packet_data); + std::vector<uint8_t> src_address_internal(src_address.data(), + src_address.data() + src_address.size()); + std::vector<uint8_t> dst_address_internal(dst_address.data(), + dst_address.data() + dst_address.size()); + return global_func_table_.wifi_start_sending_offloaded_packet( + cmd_id, getIfaceHandle(iface_name), ether_type, 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(const std::string& iface_name, + uint32_t cmd_id) { + return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id, + getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario) { + return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario); +} + +wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) { + return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) { + return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode); +} + +wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode, + uint32_t completion_window) { + return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode, + completion_window); +} + +wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end, + uint32_t access_category) { + return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end, + access_category); +} + +wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() { + return global_func_table_.wifi_reset_dscp_mapping(global_handle_); +} + +std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet( + const std::string& iface_name) { + uint32_t supported_feature_flags = 0; + wifi_error status = WIFI_SUCCESS; + + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + if (iface_handle) { + status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle, + &supported_feature_flags); + } + return {status, supported_feature_flags}; +} + +wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) { + return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name)); +} + +std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates( + const std::string& iface_name) { + std::vector<wifi_tx_report> 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( + getIfaceHandle(iface_name), 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<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates( + const std::string& iface_name) { + std::vector<wifi_rx_report> 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( + getIfaceHandle(iface_name), 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<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats( + const std::string& iface_name) { + 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<int32_t*>(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<int32_t*>(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(getIfaceHandle(iface_name), + &stats.wake_reason_cnt); + + CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 && + static_cast<uint32_t>(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<uint32_t>(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 std::string& iface_name, 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<uint8_t> buffer_vector(reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + on_user_data_callback(ring_name, buffer_vector, *status); + } + }; + wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name), + {onAsyncRingBufferData}); + if (status != WIFI_SUCCESS) { + on_ring_buffer_data_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) { + 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, getIfaceHandle(iface_name)); +} + +std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> WifiLegacyHal::getRingBuffersStatus( + const std::string& iface_name) { + std::vector<wifi_ring_buffer_status> ring_buffers_status; + ring_buffers_status.resize(kMaxRingBuffers); + uint32_t num_rings = kMaxRingBuffers; + wifi_error status = global_func_table_.wifi_get_ring_buffers_status( + getIfaceHandle(iface_name), &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& iface_name, + 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(getIfaceHandle(iface_name), verbose_level, 0, + max_interval_sec, min_data_size, + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name, + const std::string& ring_name) { + return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name), + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler( + const std::string& iface_name, 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<uint8_t>(reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size)); + } + }; + wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name), + {onAsyncErrorAlert}); + if (status != WIFI_SUCCESS) { + on_error_alert_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) { + 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, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback) { + if (on_radio_mode_change_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_radio_mode_change_internal_callback = [on_user_change_callback]( + wifi_request_id /* id */, uint32_t num_macs, + wifi_mac_info* mac_infos_arr) { + if (num_macs > 0 && mac_infos_arr) { + std::vector<WifiMacInfo> mac_infos_vec; + for (uint32_t i = 0; i < num_macs; i++) { + WifiMacInfo mac_info; + mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id; + mac_info.mac_band = mac_infos_arr[i].mac_band; + for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) { + WifiIfaceInfo iface_info; + iface_info.name = mac_infos_arr[i].iface_info[j].iface_name; + iface_info.channel = mac_infos_arr[i].iface_info[j].channel; + mac_info.iface_infos.push_back(iface_info); + } + mac_infos_vec.push_back(mac_info); + } + on_user_change_callback(mac_infos_vec); + } + }; + wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler( + 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange}); + if (status != WIFI_SUCCESS) { + on_radio_mode_change_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback) { + if (on_subsystem_restart_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) { + on_restart_callback(error); + }; + wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler( + global_handle_, {onAsyncSubsystemRestart}); + if (status != WIFI_SUCCESS) { + on_subsystem_restart_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::startRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<wifi_rtt_config>& 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<const wifi_rtt_result*> 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<wifi_rtt_config> rtt_configs_internal(rtt_configs); + wifi_error status = global_func_table_.wifi_rtt_range_request( + id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(), + {onAsyncRttResults}); + if (status != WIFI_SUCCESS) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::cancelRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<std::array<uint8_t, 6>>& mac_addrs) { + if (!on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>), "MAC address size mismatch"); + // TODO: How do we handle partial cancels (i.e only a subset of enabled mac + // addressed are cancelled). + std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs); + wifi_error status = global_func_table_.wifi_rtt_range_cancel( + id, getIfaceHandle(iface_name), mac_addrs.size(), + reinterpret_cast<mac_addr*>(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<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities( + const std::string& iface_name) { + wifi_rtt_capabilities rtt_caps; + wifi_error status = + global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps); + return {status, rtt_caps}; +} + +std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo( + const std::string& iface_name) { + wifi_rtt_responder rtt_responder; + wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name), + &rtt_responder); + return {status, rtt_responder}; +} + +wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, 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, getIfaceHandle(iface_name), channel_hint, + max_duration_secs, &info_internal); +} + +wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) { + return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id, + const wifi_lci_information& info) { + wifi_lci_information info_internal(info); + return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal); +} + +wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id, + const wifi_lcr_information& info) { + wifi_lcr_information info_internal(info); + return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal); +} + +wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name, + 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; + on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update; + + return global_func_table_.wifi_nan_register_handler( + getIfaceHandle(iface_name), + {onAysncNanNotifyResponse, onAysncNanEventPublishReplied, + onAysncNanEventPublishTerminated, onAysncNanEventMatch, onAysncNanEventMatchExpired, + onAysncNanEventSubscribeTerminated, onAysncNanEventFollowup, + onAysncNanEventDiscEngEvent, onAysncNanEventDisabled, onAysncNanEventTca, + onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest, + onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd, + onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest, + onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate}); +} + +wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id, + const NanEnableRequest& msg) { + NanEnableRequest msg_internal(msg); + return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) { + return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id, + const NanPublishRequest& msg) { + NanPublishRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id, + const NanPublishCancelRequest& msg) { + NanPublishCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeRequest& msg) { + NanSubscribeRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name, + transaction_id id, + const NanSubscribeCancelRequest& msg) { + NanSubscribeCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name, + transaction_id id, + const NanTransmitFollowupRequest& msg) { + NanTransmitFollowupRequest msg_internal(msg); + return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id, + const NanStatsRequest& msg) { + NanStatsRequest msg_internal(msg); + return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id, + const NanConfigRequest& msg) { + NanConfigRequest msg_internal(msg); + return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id, + const NanTCARequest& msg) { + NanTCARequest msg_internal(msg); + return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name, + transaction_id id, + const NanBeaconSdfPayloadRequest& msg) { + NanBeaconSdfPayloadRequest msg_internal(msg); + return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() { + NanVersion version; + wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version); + return {status, version}; +} + +wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) { + return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name), + makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name), + makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id, + const NanDataPathInitiatorRequest& msg) { + NanDataPathInitiatorRequest msg_internal(msg); + return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name, + transaction_id id, + const NanDataPathIndicationResponse& msg) { + NanDataPathIndicationResponse msg_internal(msg); + return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name), + &msg_internal); +} + +typedef struct { + u8 num_ndp_instances; + NanDataPathId ndp_instance_id; +} NanDataPathEndSingleNdpIdRequest; + +wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, 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, getIfaceHandle(iface_name), + (NanDataPathEndRequest*)&msg); + return status; +} + +wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name, + std::array<int8_t, 2> code) { + std::string code_str(code.data(), code.data() + code.size()); + return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str()); +} + +wifi_error WifiLegacyHal::retrieveIfaceHandles() { + 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; + } + iface_name_to_handle_.clear(); + for (int i = 0; i < num_iface_handles; ++i) { + std::array<char, IFNAMSIZ> iface_name_arr = {}; + status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(), + iface_name_arr.size()); + if (status != WIFI_SUCCESS) { + LOG(WARNING) << "Failed to get interface handle name"; + continue; + } + // Assuming the interface name is null terminated since the legacy HAL + // API does not return a size. + std::string iface_name(iface_name_arr.data()); + LOG(INFO) << "Adding interface handle for " << iface_name; + iface_name_to_handle_[iface_name] = iface_handles[i]; + } + return WIFI_SUCCESS; +} + +wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) { + const auto iface_handle_iter = iface_name_to_handle_.find(iface_name); + if (iface_handle_iter == iface_name_to_handle_.end()) { + LOG(ERROR) << "Unknown iface name: " << iface_name; + return nullptr; + } + return iface_handle_iter->second; +} + +void WifiLegacyHal::runEventLoop() { + LOG(DEBUG) << "Starting legacy HAL event loop"; + global_func_table_.wifi_event_loop(global_handle_); + const auto lock = hidl_sync_util::acquireGlobalLock(); + 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; + stop_wait_cv_.notify_one(); +} + +std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults( + const std::string& iface_name) { + std::vector<wifi_cached_scan_results> cached_scan_results; + cached_scan_results.resize(kMaxCachedGscanResults); + int32_t num_results = 0; + wifi_error status = global_func_table_.wifi_get_cached_gscan_results( + getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(), + cached_scan_results.data(), &num_results); + CHECK(num_results >= 0 && static_cast<uint32_t>(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(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length; + scan_result.ie_length = 0; + } + } + } + return {status, std::move(cached_scan_results)}; +} + +wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype) { + // Create the interface if it doesn't exist. If interface already exist, + // Vendor Hal should return WIFI_SUCCESS. + wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_, + ifname.c_str(), iftype); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) { + // Delete the interface if it was created dynamically. + wifi_error status = + global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str()); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname, + wifi_error status) { + if (status == WIFI_SUCCESS) { + // refresh list of handlers now. + status = retrieveIfaceHandles(); + } else if (status == WIFI_ERROR_NOT_SUPPORTED) { + // Vendor hal does not implement this API. Such vendor implementations + // are expected to create / delete interface by other means. + + // check if interface exists. + if (if_nametoindex(ifname.c_str())) { + status = retrieveIfaceHandles(); + } + } + return status; +} + +wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) { + std::array<char, IFNAMSIZ> buffer; + + wifi_error res = global_func_table_.wifi_get_supported_iface_name( + global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size()); + if (res == WIFI_SUCCESS) ifname = buffer.data(); + + return res; +} + +wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) { + return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_, + getIfaceHandle(ifname)); +} + +wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) { + return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case); +} + +wifi_error WifiLegacyHal::setCoexUnsafeChannels( + std::vector<wifi_coex_unsafe_channel> unsafe_channels, uint32_t restrictions) { + return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(), + unsafe_channels.data(), restrictions); +} + +wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) { + return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode); +} + +wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name, + const TwtCallbackHandlers& user_callbacks) { + on_twt_event_setup_response_callback = user_callbacks.on_setup_response; + on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion; + on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received; + on_twt_event_device_notify_callback = user_callbacks.on_device_notify; + + return global_func_table_.wifi_twt_register_handler( + getIfaceHandle(iface_name), + {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion, + onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify}); +} + +std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability( + const std::string& iface_name) { + TwtCapabilitySet capSet; + wifi_error status = + global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet); + return {status, capSet}; +} + +wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name, + const TwtSetupRequest& msg) { + TwtSetupRequest msgInternal(msg); + return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal); +} + +wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name, + const TwtTeardownRequest& msg) { + TwtTeardownRequest msgInternal(msg); + return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal); +} + +wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name, + const TwtInfoFrameRequest& msg) { + TwtInfoFrameRequest msgInternal(msg); + return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal); +} + +std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(const std::string& iface_name, + uint8_t configId) { + TwtStats stats; + wifi_error status = + global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats); + return {status, stats}; +} + +wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) { + return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId); +} + +wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) { + return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier); +} + +std::pair<wifi_error, std::vector<wifi_usable_channel>> WifiLegacyHal::getUsableChannels( + uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) { + std::vector<wifi_usable_channel> channels; + channels.resize(kMaxWifiUsableChannels); + uint32_t size = 0; + wifi_error status = global_func_table_.wifi_get_usable_channels( + global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size, + reinterpret_cast<wifi_usable_channel*>(channels.data())); + CHECK(size >= 0 && size <= kMaxWifiUsableChannels); + channels.resize(size); + return {status, std::move(channels)}; +} + +wifi_error WifiLegacyHal::triggerSubsystemRestart() { + return global_func_table_.wifi_trigger_subsystem_restart(global_handle_); +} + +wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) { + return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor); +} + +std::pair<wifi_error, wifi_radio_combination_matrix*> +WifiLegacyHal::getSupportedRadioCombinationsMatrix() { + char* buffer = new char[kMaxSupportedRadioCombinationsMatrixLength]; + std::fill(buffer, buffer + kMaxSupportedRadioCombinationsMatrixLength, 0); + uint32_t size = 0; + wifi_radio_combination_matrix* radio_combination_matrix_ptr = + reinterpret_cast<wifi_radio_combination_matrix*>(buffer); + wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix( + global_handle_, kMaxSupportedRadioCombinationsMatrixLength, &size, + radio_combination_matrix_ptr); + CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength); + return {status, radio_combination_matrix_ptr}; +} + +wifi_error WifiLegacyHal::chreNanRttRequest(const std::string& iface_name, bool enable) { + if (enable) + return global_func_table_.wifi_nan_rtt_chre_enable_request(0, getIfaceHandle(iface_name), + NULL); + else + return global_func_table_.wifi_nan_rtt_chre_disable_request(0, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::chreRegisterHandler(const std::string& iface_name, + const ChreCallbackHandlers& handler) { + if (on_chre_nan_rtt_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_chre_nan_rtt_internal_callback = handler.on_wifi_chre_nan_rtt_state; + + wifi_error status = global_func_table_.wifi_chre_register_handler(getIfaceHandle(iface_name), + {onAsyncChreNanRttState}); + if (status != WIFI_SUCCESS) { + on_chre_nan_rtt_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::enableWifiTxPowerLimits(const std::string& iface_name, bool enable) { + return global_func_table_.wifi_enable_tx_power_limits(getIfaceHandle(iface_name), enable); +} + +wifi_error WifiLegacyHal::getWifiCachedScanResults( + const std::string& iface_name, const CachedScanResultsCallbackHandlers& handler) { + on_cached_scan_results_internal_callback = handler.on_cached_scan_results; + + wifi_error status = global_func_table_.wifi_get_cached_scan_results(getIfaceHandle(iface_name), + {onSyncCachedScanResults}); + + on_cached_scan_results_internal_callback = nullptr; + return status; +} + +void WifiLegacyHal::invalidate() { + global_handle_ = nullptr; + iface_name_to_handle_.clear(); + 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_radio_mode_change_internal_callback = nullptr; + on_subsystem_restart_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; + on_nan_event_schedule_update_user_callback = nullptr; + on_twt_event_setup_response_callback = nullptr; + on_twt_event_teardown_completion_callback = nullptr; + on_twt_event_info_frame_received_callback = nullptr; + on_twt_event_device_notify_callback = nullptr; + on_chre_nan_rtt_internal_callback = nullptr; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h new file mode 100644 index 0000000..b6bd5ea --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h @@ -0,0 +1,739 @@ +/* + * 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 <condition_variable> +#include <functional> +#include <map> +#include <thread> +#include <vector> + +#include <hal_legacy/wifi_hal.h> +#include <wifi_system/interface_tool.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +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 { +// Import all the types defined inside the legacy HAL header files into this +// namespace. +using ::chre_nan_rtt_state; +using ::frame_info; +using ::frame_type; +using ::FRAME_TYPE_80211_MGMT; +using ::FRAME_TYPE_ETHERNET_II; +using ::FRAME_TYPE_UNKNOWN; +using ::fw_roaming_state_t; +using ::mac_addr; +using ::NAN_CHANNEL_24G_BAND; +using ::NAN_CHANNEL_5G_BAND_HIGH; +using ::NAN_CHANNEL_5G_BAND_LOW; +using ::NAN_DISABLE_RANGE_REPORT; +using ::NAN_DO_NOT_USE_SRF; +using ::NAN_DP_CHANNEL_NOT_REQUESTED; +using ::NAN_DP_CONFIG_NO_SECURITY; +using ::NAN_DP_CONFIG_SECURITY; +using ::NAN_DP_END; +using ::NAN_DP_FORCE_CHANNEL_SETUP; +using ::NAN_DP_INITIATOR_RESPONSE; +using ::NAN_DP_INTERFACE_CREATE; +using ::NAN_DP_INTERFACE_DELETE; +using ::NAN_DP_REQUEST_ACCEPT; +using ::NAN_DP_REQUEST_CHANNEL_SETUP; +using ::NAN_DP_REQUEST_REJECT; +using ::NAN_DP_RESPONDER_RESPONSE; +using ::NAN_GET_CAPABILITIES; +using ::NAN_MATCH_ALG_MATCH_CONTINUOUS; +using ::NAN_MATCH_ALG_MATCH_NEVER; +using ::NAN_MATCH_ALG_MATCH_ONCE; +using ::NAN_PUBLISH_TYPE_SOLICITED; +using ::NAN_PUBLISH_TYPE_UNSOLICITED; +using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED; +using ::NAN_RANGING_AUTO_RESPONSE_DISABLE; +using ::NAN_RANGING_AUTO_RESPONSE_ENABLE; +using ::NAN_RANGING_DISABLE; +using ::NAN_RANGING_ENABLE; +using ::NAN_RESPONSE_BEACON_SDF_PAYLOAD; +using ::NAN_RESPONSE_CONFIG; +using ::NAN_RESPONSE_DISABLED; +using ::NAN_RESPONSE_ENABLED; +using ::NAN_RESPONSE_ERROR; +using ::NAN_RESPONSE_PUBLISH; +using ::NAN_RESPONSE_PUBLISH_CANCEL; +using ::NAN_RESPONSE_STATS; +using ::NAN_RESPONSE_SUBSCRIBE; +using ::NAN_RESPONSE_SUBSCRIBE_CANCEL; +using ::NAN_RESPONSE_TCA; +using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP; +using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE; +using ::NAN_SECURITY_KEY_INPUT_PMK; +using ::NAN_SERVICE_ACCEPT_POLICY_ALL; +using ::NAN_SERVICE_ACCEPT_POLICY_NONE; +using ::NAN_SRF_ATTR_BLOOM_FILTER; +using ::NAN_SRF_ATTR_PARTIAL_MAC_ADDR; +using ::NAN_SRF_INCLUDE_DO_NOT_RESPOND; +using ::NAN_SRF_INCLUDE_RESPOND; +using ::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; +using ::NAN_SSI_REQUIRED_IN_MATCH_IND; +using ::NAN_STATUS_ALREADY_ENABLED; +using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL; +using ::NAN_STATUS_INTERNAL_FAILURE; +using ::NAN_STATUS_INVALID_NDP_ID; +using ::NAN_STATUS_INVALID_PARAM; +using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; +using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID; +using ::NAN_STATUS_NAN_NOT_ALLOWED; +using ::NAN_STATUS_NO_OTA_ACK; +using ::NAN_STATUS_NO_RESOURCE_AVAILABLE; +using ::NAN_STATUS_PROTOCOL_FAILURE; +using ::NAN_STATUS_SUCCESS; +using ::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED; +using ::NAN_SUBSCRIBE_TYPE_ACTIVE; +using ::NAN_SUBSCRIBE_TYPE_PASSIVE; +using ::NAN_TRANSMIT_IN_DW; +using ::NAN_TRANSMIT_IN_FAW; +using ::NAN_TX_PRIORITY_HIGH; +using ::NAN_TX_PRIORITY_NORMAL; +using ::NAN_TX_TYPE_BROADCAST; +using ::NAN_TX_TYPE_UNICAST; +using ::NAN_USE_SRF; +using ::NanBeaconSdfPayloadInd; +using ::NanCapabilities; +using ::NanChannelInfo; +using ::NanConfigRequest; +using ::NanDataPathChannelCfg; +using ::NanDataPathConfirmInd; +using ::NanDataPathEndInd; +using ::NanDataPathIndicationResponse; +using ::NanDataPathInitiatorRequest; +using ::NanDataPathRequestInd; +using ::NanDataPathScheduleUpdateInd; +using ::NanDisabledInd; +using ::NanDiscEngEventInd; +using ::NanEnableRequest; +using ::NanFollowupInd; +using ::NanMatchAlg; +using ::NanMatchExpiredInd; +using ::NanMatchInd; +using ::NanPublishCancelRequest; +using ::NanPublishRequest; +using ::NanPublishTerminatedInd; +using ::NanPublishType; +using ::NanRangeReportInd; +using ::NanRangeRequestInd; +using ::NanResponseMsg; +using ::NanSRFType; +using ::NanStatusType; +using ::NanSubscribeCancelRequest; +using ::NanSubscribeRequest; +using ::NanSubscribeTerminatedInd; +using ::NanSubscribeType; +using ::NanTransmitFollowupInd; +using ::NanTransmitFollowupRequest; +using ::NanTxType; +using ::ROAMING_DISABLE; +using ::ROAMING_ENABLE; +using ::RTT_PEER_AP; +using ::RTT_PEER_NAN; +using ::RTT_PEER_P2P_CLIENT; +using ::RTT_PEER_P2P_GO; +using ::RTT_PEER_STA; +using ::rtt_peer_type; +using ::RTT_STATUS_ABORTED; +using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; +using ::RTT_STATUS_FAIL_BUSY_TRY_LATER; +using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; +using ::RTT_STATUS_FAIL_INVALID_TS; +using ::RTT_STATUS_FAIL_NO_CAPABILITY; +using ::RTT_STATUS_FAIL_NO_RSP; +using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET; +using ::RTT_STATUS_FAIL_PROTOCOL; +using ::RTT_STATUS_FAIL_REJECTED; +using ::RTT_STATUS_FAIL_SCHEDULE; +using ::RTT_STATUS_FAIL_TM_TIMEOUT; +using ::RTT_STATUS_FAILURE; +using ::RTT_STATUS_INVALID_REQ; +using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED; +using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE; +using ::RTT_STATUS_NO_WIFI; +using ::RTT_STATUS_SUCCESS; +using ::RTT_TYPE_1_SIDED; +using ::RTT_TYPE_2_SIDED; +using ::RX_PKT_FATE_DRV_DROP_FILTER; +using ::RX_PKT_FATE_DRV_DROP_INVALID; +using ::RX_PKT_FATE_DRV_DROP_NOBUFS; +using ::RX_PKT_FATE_DRV_DROP_OTHER; +using ::RX_PKT_FATE_DRV_QUEUED; +using ::RX_PKT_FATE_FW_DROP_FILTER; +using ::RX_PKT_FATE_FW_DROP_INVALID; +using ::RX_PKT_FATE_FW_DROP_NOBUFS; +using ::RX_PKT_FATE_FW_DROP_OTHER; +using ::RX_PKT_FATE_FW_QUEUED; +using ::RX_PKT_FATE_SUCCESS; +using ::ssid_t; +using ::transaction_id; +using ::TX_PKT_FATE_ACKED; +using ::TX_PKT_FATE_DRV_DROP_INVALID; +using ::TX_PKT_FATE_DRV_DROP_NOBUFS; +using ::TX_PKT_FATE_DRV_DROP_OTHER; +using ::TX_PKT_FATE_DRV_QUEUED; +using ::TX_PKT_FATE_FW_DROP_INVALID; +using ::TX_PKT_FATE_FW_DROP_NOBUFS; +using ::TX_PKT_FATE_FW_DROP_OTHER; +using ::TX_PKT_FATE_FW_QUEUED; +using ::TX_PKT_FATE_SENT; +using ::WIFI_AC_BE; +using ::WIFI_AC_BK; +using ::WIFI_AC_VI; +using ::WIFI_AC_VO; +using ::WIFI_ANTENNA_1X1; +using ::WIFI_ANTENNA_2X2; +using ::WIFI_ANTENNA_3X3; +using ::WIFI_ANTENNA_4X4; +using ::WIFI_ANTENNA_UNSPECIFIED; +using ::wifi_band; +using ::WIFI_BAND_A; +using ::WIFI_BAND_A_DFS; +using ::WIFI_BAND_A_WITH_DFS; +using ::WIFI_BAND_ABG; +using ::WIFI_BAND_ABG_WITH_DFS; +using ::WIFI_BAND_BG; +using ::WIFI_BAND_UNSPECIFIED; +using ::wifi_cached_scan_report; +using ::wifi_cached_scan_results; +using ::WIFI_CHAN_WIDTH_10; +using ::WIFI_CHAN_WIDTH_160; +using ::WIFI_CHAN_WIDTH_20; +using ::WIFI_CHAN_WIDTH_320; +using ::WIFI_CHAN_WIDTH_40; +using ::WIFI_CHAN_WIDTH_5; +using ::WIFI_CHAN_WIDTH_80; +using ::WIFI_CHAN_WIDTH_80P80; +using ::WIFI_CHAN_WIDTH_INVALID; +using ::wifi_channel_info; +using ::wifi_channel_stat; +using ::wifi_channel_width; +using ::wifi_coex_restriction; +using ::wifi_coex_unsafe_channel; +using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; +using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; +using ::wifi_error; +using ::WIFI_ERROR_BUSY; +using ::WIFI_ERROR_INVALID_ARGS; +using ::WIFI_ERROR_INVALID_REQUEST_ID; +using ::WIFI_ERROR_NONE; +using ::WIFI_ERROR_NOT_AVAILABLE; +using ::WIFI_ERROR_NOT_SUPPORTED; +using ::WIFI_ERROR_OUT_OF_MEMORY; +using ::WIFI_ERROR_TIMED_OUT; +using ::WIFI_ERROR_TOO_MANY_REQUESTS; +using ::WIFI_ERROR_UNINITIALIZED; +using ::WIFI_ERROR_UNKNOWN; +using ::wifi_gscan_capabilities; +using ::wifi_hal_fn; +using ::wifi_information_element; +using ::WIFI_INTERFACE_IBSS; +using ::WIFI_INTERFACE_MESH; +using ::wifi_interface_mode; +using ::WIFI_INTERFACE_NAN; +using ::WIFI_INTERFACE_P2P_CLIENT; +using ::WIFI_INTERFACE_P2P_GO; +using ::WIFI_INTERFACE_SOFTAP; +using ::WIFI_INTERFACE_STA; +using ::WIFI_INTERFACE_TDLS; +using ::wifi_interface_type; +using ::WIFI_INTERFACE_TYPE_AP; +using ::WIFI_INTERFACE_TYPE_NAN; +using ::WIFI_INTERFACE_TYPE_P2P; +using ::WIFI_INTERFACE_TYPE_STA; +using ::WIFI_INTERFACE_UNKNOWN; +using ::wifi_latency_mode; +using ::WIFI_LATENCY_MODE_LOW; +using ::WIFI_LATENCY_MODE_NORMAL; +using ::wifi_lci_information; +using ::wifi_lcr_information; +using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; +using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED; +using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; +using ::WIFI_LOGGER_PACKET_FATE_SUPPORTED; +using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED; +using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED; +using ::WIFI_MOTION_EXPECTED; +using ::WIFI_MOTION_NOT_EXPECTED; +using ::wifi_motion_pattern; +using ::WIFI_MOTION_UNKNOWN; +using ::wifi_multi_sta_use_case; +using ::wifi_power_scenario; +using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; +using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; +using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; +using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; +using ::WIFI_POWER_SCENARIO_VOICE_CALL; +using ::wifi_radio_combination; +using ::wifi_radio_combination_matrix; +using ::wifi_radio_configuration; +using ::wifi_rate; +using ::wifi_request_id; +using ::wifi_ring_buffer_status; +using ::wifi_roaming_capabilities; +using ::wifi_roaming_config; +using ::wifi_rtt_bw; +using ::WIFI_RTT_BW_10; +using ::WIFI_RTT_BW_160; +using ::WIFI_RTT_BW_20; +using ::WIFI_RTT_BW_320; +using ::WIFI_RTT_BW_40; +using ::WIFI_RTT_BW_5; +using ::WIFI_RTT_BW_80; +using ::wifi_rtt_capabilities; +using ::wifi_rtt_config; +using ::wifi_rtt_preamble; +using ::WIFI_RTT_PREAMBLE_EHT; +using ::WIFI_RTT_PREAMBLE_HE; +using ::WIFI_RTT_PREAMBLE_HT; +using ::WIFI_RTT_PREAMBLE_LEGACY; +using ::WIFI_RTT_PREAMBLE_VHT; +using ::wifi_rtt_responder; +using ::wifi_rtt_result; +using ::wifi_rtt_status; +using ::wifi_rtt_type; +using ::wifi_rx_packet_fate; +using ::wifi_rx_report; +using ::wifi_scan_bucket_spec; +using ::wifi_scan_cmd_params; +using ::WIFI_SCAN_FLAG_INTERRUPTED; +using ::wifi_scan_result; +using ::WIFI_SUCCESS; +using ::wifi_tx_packet_fate; +using ::wifi_tx_report; +using ::wifi_usable_channel; +using ::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; +using ::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; +using ::WLAN_MAC_2_4_BAND; +using ::WLAN_MAC_5_0_BAND; +using ::WLAN_MAC_60_0_BAND; +using ::WLAN_MAC_6_0_BAND; + +// 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<uint32_t> tx_time_per_levels; + std::vector<wifi_channel_stat> channel_stats; +}; + +struct WifiPeerInfo { + wifi_peer_info peer_info; + std::vector<wifi_rate_stat> rate_stats; +}; + +struct LinkLayerStats { + wifi_iface_stat iface; + std::vector<LinkLayerRadioStats> radios; + std::vector<WifiPeerInfo> peers; +}; +#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<uint32_t> cmd_event_wake_cnt; + std::vector<uint32_t> driver_fw_local_wake_cnt; +}; + +// NAN response and event callbacks struct. +struct NanCallbackHandlers { + // NotifyResponse invoked to notify the status of the Request. + std::function<void(transaction_id, const NanResponseMsg&)> on_notify_response; + // Various event callbacks. + std::function<void(const NanPublishTerminatedInd&)> on_event_publish_terminated; + std::function<void(const NanMatchInd&)> on_event_match; + std::function<void(const NanMatchExpiredInd&)> on_event_match_expired; + std::function<void(const NanSubscribeTerminatedInd&)> on_event_subscribe_terminated; + std::function<void(const NanFollowupInd&)> on_event_followup; + std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event; + std::function<void(const NanDisabledInd&)> on_event_disabled; + std::function<void(const NanTCAInd&)> on_event_tca; + std::function<void(const NanBeaconSdfPayloadInd&)> on_event_beacon_sdf_payload; + std::function<void(const NanDataPathRequestInd&)> on_event_data_path_request; + std::function<void(const NanDataPathConfirmInd&)> on_event_data_path_confirm; + std::function<void(const NanDataPathEndInd&)> on_event_data_path_end; + std::function<void(const NanTransmitFollowupInd&)> on_event_transmit_follow_up; + std::function<void(const NanRangeRequestInd&)> on_event_range_request; + std::function<void(const NanRangeReportInd&)> on_event_range_report; + std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update; +}; + +// 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<void(wifi_request_id, const wifi_scan_result*, uint32_t)>; +// These scan results don't contain any IE info, so no need to pass by +// reference. +using on_gscan_results_callback = + std::function<void(wifi_request_id, const std::vector<wifi_cached_scan_results>&)>; + +// Invoked when the rssi value breaches the thresholds set. +using on_rssi_threshold_breached_callback = + std::function<void(wifi_request_id, std::array<uint8_t, 6>, 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<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>; + +// Callback for ring buffer data. +using on_ring_buffer_data_callback = std::function<void( + const std::string&, const std::vector<uint8_t>&, const wifi_ring_buffer_status&)>; + +// Callback for alerts. +using on_error_alert_callback = std::function<void(int32_t, const std::vector<uint8_t>&)>; + +// Callback for subsystem restart +using on_subsystem_restart_callback = std::function<void(const std::string&)>; + +// Struct for the mac info from the legacy HAL. This is a cleaner version +// of the |wifi_mac_info| & |wifi_iface_info|. +typedef struct { + std::string name; + wifi_channel channel; +} WifiIfaceInfo; + +typedef struct { + uint32_t wlan_mac_id; + /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */ + uint32_t mac_band; + /* Represents the connected Wi-Fi interfaces associated with each MAC */ + std::vector<WifiIfaceInfo> iface_infos; +} WifiMacInfo; + +// Callback for radio mode change +using on_radio_mode_change_callback = std::function<void(const std::vector<WifiMacInfo>&)>; + +// TWT response and event callbacks struct. +struct TwtCallbackHandlers { + // Callback for TWT setup response + std::function<void(const TwtSetupResponse&)> on_setup_response; + // Callback for TWT teardown completion + std::function<void(const TwtTeardownCompletion&)> on_teardown_completion; + // Callback for TWT info frame received event + std::function<void(const TwtInfoFrameReceived&)> on_info_frame_received; + // Callback for TWT notification from the device + std::function<void(const TwtDeviceNotify&)> on_device_notify; +}; + +// CHRE response and event callbacks struct. +struct ChreCallbackHandlers { + // Callback for CHRE NAN RTT + std::function<void(chre_nan_rtt_state)> on_wifi_chre_nan_rtt_state; +}; + +// Cached Scan Results response and event callbacks struct. +struct CachedScanResultsCallbackHandlers { + // Callback for Cached Scan Results + std::function<void(wifi_cached_scan_report*)> on_cached_scan_results; +}; + +/** + * Class that encapsulates all legacy HAL interactions. + * This class manages the lifetime of the event loop thread used by legacy HAL. + * + * Note: There 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(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, const wifi_hal_fn& fn, + bool is_primary); + virtual ~WifiLegacyHal() = default; + + // Initialize the legacy HAL function table. + virtual wifi_error initialize(); + // Start the legacy HAL and the event looper thread. + virtual wifi_error start(); + // Deinitialize the legacy HAL and wait for the event loop thread to exit + // using a predefined timeout. + virtual wifi_error stop(std::unique_lock<std::recursive_mutex>* lock, + const std::function<void()>& on_complete_callback); + virtual wifi_error waitForDriverReady(); + // Checks if legacy HAL has successfully started + bool isStarted(); + // Wrappers for all the functions in the legacy HAL function table. + virtual std::pair<wifi_error, std::string> getDriverVersion(const std::string& iface_name); + virtual std::pair<wifi_error, std::string> getFirmwareVersion(const std::string& iface_name); + std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump( + const std::string& iface_name); + std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump( + const std::string& iface_name); + virtual std::pair<wifi_error, uint64_t> getSupportedFeatureSet(const std::string& iface_name); + // APF functions. + std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities( + const std::string& iface_name); + wifi_error setPacketFilter(const std::string& iface_name, const std::vector<uint8_t>& program); + std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData( + const std::string& iface_name); + // Gscan functions. + std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities( + const std::string& iface_name); + // 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(const std::string& iface_name, wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function<void(wifi_request_id)>& on_failure_callback, + const on_gscan_results_callback& on_results_callback, + const on_gscan_full_result_callback& on_full_result_callback); + wifi_error stopGscan(const std::string& iface_name, wifi_request_id id); + std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand( + const std::string& iface_name, wifi_band band); + virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on); + // Link layer stats functions. + wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug); + wifi_error disableLinkLayerStats(const std::string& iface_name); + std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(const std::string& iface_name); + // RSSI monitor functions. + wifi_error startRssiMonitoring( + const std::string& iface_name, 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(const std::string& iface_name, wifi_request_id id); + std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities( + const std::string& iface_name); + wifi_error configureRoaming(const std::string& iface_name, const wifi_roaming_config& config); + wifi_error enableFirmwareRoaming(const std::string& iface_name, fw_roaming_state_t state); + wifi_error configureNdOffload(const std::string& iface_name, bool enable); + wifi_error startSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id, + uint16_t ether_type, + const std::vector<uint8_t>& ip_packet_data, + const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, + uint32_t period_in_ms); + wifi_error stopSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id); + virtual wifi_error selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario); + virtual wifi_error resetTxPowerScenario(const std::string& iface_name); + wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode); + wifi_error setThermalMitigationMode(wifi_thermal_mode mode, uint32_t completion_window); + wifi_error setDscpToAccessCategoryMapping(uint32_t start, uint32_t end, + uint32_t access_category); + wifi_error resetDscpToAccessCategoryMapping(); + // Logger/debug functions. + std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(const std::string& iface_name); + wifi_error startPktFateMonitoring(const std::string& iface_name); + std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(const std::string& iface_name); + std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(const std::string& iface_name); + std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(const std::string& iface_name); + wifi_error registerRingBufferCallbackHandler( + const std::string& iface_name, const on_ring_buffer_data_callback& on_data_callback); + wifi_error deregisterRingBufferCallbackHandler(const std::string& iface_name); + virtual wifi_error registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback); + std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> getRingBuffersStatus( + const std::string& iface_name); + wifi_error startRingBufferLogging(const std::string& iface_name, 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& iface_name, const std::string& ring_name); + wifi_error registerErrorAlertCallbackHandler(const std::string& iface_name, + const on_error_alert_callback& on_alert_callback); + wifi_error deregisterErrorAlertCallbackHandler(const std::string& iface_name); + // Radio mode functions. + virtual wifi_error registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback); + // RTT functions. + wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id, + const std::vector<wifi_rtt_config>& rtt_configs, + const on_rtt_results_callback& on_results_callback); + wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id, + const std::vector<std::array<uint8_t, 6>>& mac_addrs); + std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name); + std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name); + wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id, + const wifi_channel_info& channel_hint, uint32_t max_duration_secs, + const wifi_rtt_responder& info); + wifi_error disableRttResponder(const std::string& iface_name, wifi_request_id id); + wifi_error setRttLci(const std::string& iface_name, wifi_request_id id, + const wifi_lci_information& info); + wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id, + const wifi_lcr_information& info); + // NAN functions. + virtual wifi_error nanRegisterCallbackHandlers(const std::string& iface_name, + const NanCallbackHandlers& callbacks); + wifi_error nanEnableRequest(const std::string& iface_name, transaction_id id, + const NanEnableRequest& msg); + virtual wifi_error nanDisableRequest(const std::string& iface_name, transaction_id id); + wifi_error nanPublishRequest(const std::string& iface_name, transaction_id id, + const NanPublishRequest& msg); + wifi_error nanPublishCancelRequest(const std::string& iface_name, transaction_id id, + const NanPublishCancelRequest& msg); + wifi_error nanSubscribeRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeRequest& msg); + wifi_error nanSubscribeCancelRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeCancelRequest& msg); + wifi_error nanTransmitFollowupRequest(const std::string& iface_name, transaction_id id, + const NanTransmitFollowupRequest& msg); + wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id, + const NanStatsRequest& msg); + wifi_error nanConfigRequest(const std::string& iface_name, transaction_id id, + const NanConfigRequest& msg); + wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id, + const NanTCARequest& msg); + wifi_error nanBeaconSdfPayloadRequest(const std::string& iface_name, transaction_id id, + const NanBeaconSdfPayloadRequest& msg); + std::pair<wifi_error, NanVersion> nanGetVersion(); + wifi_error nanGetCapabilities(const std::string& iface_name, transaction_id id); + wifi_error nanDataInterfaceCreate(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name); + virtual wifi_error nanDataInterfaceDelete(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name); + wifi_error nanDataRequestInitiator(const std::string& iface_name, transaction_id id, + const NanDataPathInitiatorRequest& msg); + wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id, + const NanDataPathIndicationResponse& msg); + wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId); + // AP functions. + wifi_error setCountryCode(const std::string& iface_name, std::array<int8_t, 2> code); + + // interface functions. + virtual wifi_error createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype); + virtual wifi_error deleteVirtualInterface(const std::string& ifname); + virtual wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname); + + // STA + STA functions + virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname); + virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case); + + // Coex functions. + virtual wifi_error setCoexUnsafeChannels(std::vector<wifi_coex_unsafe_channel> unsafe_channels, + uint32_t restrictions); + + wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode); + + wifi_error twtRegisterHandler(const std::string& iface_name, + const TwtCallbackHandlers& handler); + + std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(const std::string& iface_name); + + wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg); + + wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg); + + wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg); + + std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name, uint8_t configId); + + wifi_error twtClearStats(const std::string& iface_name, uint8_t configId); + + wifi_error setDtimConfig(const std::string& iface_name, uint32_t multiplier); + + // Retrieve the list of usable channels in the requested bands + // for the requested modes + std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels( + uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask); + + wifi_error triggerSubsystemRestart(); + + wifi_error setIndoorState(bool isIndoor); + + std::pair<wifi_error, wifi_radio_combination_matrix*> getSupportedRadioCombinationsMatrix(); + + // CHRE NAN RTT function + wifi_error chreNanRttRequest(const std::string& iface_name, bool enable); + + wifi_error chreRegisterHandler(const std::string& iface_name, + const ChreCallbackHandlers& handler); + + wifi_error enableWifiTxPowerLimits(const std::string& iface_name, bool enable); + wifi_error getWifiCachedScanResults(const std::string& iface_name, + const CachedScanResultsCallbackHandlers& handler); + + private: + // Retrieve interface handles for all the available interfaces. + wifi_error retrieveIfaceHandles(); + wifi_interface_handle getIfaceHandle(const std::string& iface_name); + // 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<wifi_error, std::vector<wifi_cached_scan_results>> getGscanCachedResults( + const std::string& iface_name); + void invalidate(); + // Handles wifi (error) status of Virtual interface create/delete + wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname, + wifi_error status); + + // 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_; + // Map of interface name to handle that is to be used for all interface + // specific operations. + std::map<std::string, wifi_interface_handle> iface_name_to_handle_; + // Flag to indicate if we have initiated the cleanup of legacy HAL. + std::atomic<bool> awaiting_event_loop_termination_; + std::condition_variable_any stop_wait_cv_; + // Flag to indicate if the legacy HAL has been started. + bool is_started_; + std::weak_ptr<wifi_system::InterfaceTool> iface_tool_; + // flag to indicate if this HAL is for the primary chip. This is used + // in order to avoid some hard-coded behavior used with older HALs, + // such as bring wlan0 interface up/down on start/stop HAL. + // it may be removed once vendor HALs are updated. + bool is_primary_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp new file mode 100644 index 0000000..147bf4d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2020 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 <dirent.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <android-base/logging.h> +#include <dlfcn.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xmlmemory.h> + +#include "wifi_legacy_hal_factory.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals"; +static constexpr char kVendorHalsDescExt[] = ".xml"; +static constexpr uint32_t kVendorHalsDescVersion = 1; + +bool isDirectory(struct dirent* entryPtr) { + bool isDir = false; + if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) { + isDir = (entryPtr->d_type == DT_DIR); + } else { + struct stat entryStat; + stat(entryPtr->d_name, &entryStat); + isDir = S_ISDIR(entryStat.st_mode); + } + return isDir; +} + +bool isFileExtension(const char* name, const char* ext) { + if (name == NULL) return false; + if (ext == NULL) return false; + + size_t extLen = strlen(ext); + size_t nameLen = strlen(name); + + if (extLen > nameLen) return false; + + if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false; + + return true; +} +}; // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { + +WifiLegacyHalFactory::WifiLegacyHalFactory( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool) + : iface_tool_(iface_tool) {} + +std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() { + if (legacy_hals_.empty()) { + if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList(); + for (auto& desc : descs_) { + std::shared_ptr<WifiLegacyHal> hal = + std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary); + legacy_hals_.push_back(hal); + } + } + + return legacy_hals_; +} + +bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() { + wifi_hal_lib_desc desc; + + if (!initLinkedHalFunctionTable(&desc.fn)) return false; + + desc.primary = true; + desc.handle = NULL; + descs_.push_back(desc); + return true; +} + +bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) { + init_wifi_vendor_hal_func_table_t initfn; + + initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT, + "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(INFO) << "no vendor HAL library linked, will try dynamic load"; + return false; + } + + if (!initHalFuncTableWithStubs(hal_fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + return false; + } + + if (initfn(hal_fn) != WIFI_SUCCESS) { + LOG(ERROR) << "Can not initialize the vendor function pointer table"; + return false; + } + + return true; +} + +/* + * Overall structure of the HAL descriptor XML schema + * + * <?xml version="1.0" encoding="UTF-8"?> + * <WifiVendorHal version="1"> + * <path>/vendor/lib64/libwifi-hal-qcom.so</path> + * <primary>1</primary> + * </WifiVendorHal> + */ +void WifiLegacyHalFactory::initVendorHalsDescriptorList() { + xmlDocPtr xml; + xmlNodePtr node, cnode; + char* version; + std::string path; + xmlChar* value; + wifi_hal_lib_desc desc; + + LOG(INFO) << "processing vendor HALs descriptions in " << kVendorHalsDescPath; + DIR* dirPtr = ::opendir(kVendorHalsDescPath); + if (dirPtr == NULL) { + LOG(ERROR) << "failed to open " << kVendorHalsDescPath; + return; + } + for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL; + entryPtr = ::readdir(dirPtr)) { + if (isDirectory(entryPtr)) continue; + + if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt)) + continue; // only process .xml files + + LOG(INFO) << "processing config file: " << entryPtr->d_name; + + std::string fullPath(kVendorHalsDescPath); + fullPath.append("/"); + fullPath.append(entryPtr->d_name); + xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER); + if (!xml) { + LOG(ERROR) << "failed to parse: " << entryPtr->d_name << " skipping..."; + continue; + } + node = xmlDocGetRootElement(xml); + if (!node) { + LOG(ERROR) << "empty config file: " << entryPtr->d_name << " skipping..."; + goto skip; + } + if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) { + LOG(ERROR) << "bad config, root element not WifiVendorHal: " << entryPtr->d_name + << " skipping..."; + goto skip; + } + version = (char*)xmlGetProp(node, BAD_CAST "version"); + if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) { + LOG(ERROR) << "conf file: " << entryPtr->d_name + << "must have version: " << kVendorHalsDescVersion << ", skipping..."; + goto skip; + } + cnode = node->children; + path.clear(); + desc.primary = false; + while (cnode) { + if (!xmlStrcmp(cnode->name, BAD_CAST "path")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + if (value) path = (char*)value; + xmlFree(value); + } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + desc.primary = !xmlStrcmp(value, BAD_CAST "1"); + xmlFree(value); + } + cnode = cnode->next; + } + if (path.empty()) { + LOG(ERROR) << "hal library path not provided in: " << entryPtr->d_name + << ", skipping..."; + goto skip; + } + if (loadVendorHalLib(path, desc)) { + if (desc.primary) + descs_.insert(descs_.begin(), desc); + else + descs_.push_back(desc); + } + skip: + xmlFreeDoc(xml); + } + ::closedir(dirPtr); +} + +bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc) { + void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); + init_wifi_vendor_hal_func_table_t initfn; + wifi_error res; + + if (!h) { + LOG(ERROR) << "failed to open vendor hal library: " << path; + return false; + } + initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path; + goto out_err; + } + + if (!initHalFuncTableWithStubs(&desc.fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + goto out_err; + } + res = initfn(&desc.fn); + if (res != WIFI_SUCCESS) { + LOG(ERROR) << "failed to initialize the vendor func table in: " << path + << " error: " << res; + goto out_err; + } + + res = desc.fn.wifi_early_initialize(); + // vendor HALs which do not implement early_initialize will return + // WIFI_ERROR_NOT_SUPPORTED, treat this as success. + if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) { + LOG(ERROR) << "early initialization failed in: " << path << " error: " << res; + goto out_err; + } + + desc.handle = h; + return true; +out_err: + dlclose(h); + return false; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h new file mode 100644 index 0000000..9f4423e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 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_FACTORY_H_ +#define WIFI_LEGACY_HAL_FACTORY_H_ + +#include <wifi_system/interface_tool.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +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 { +/** + * Class that creates WifiLegacyHal objects for vendor HALs in the system. + */ +class WifiLegacyHalFactory { + public: + WifiLegacyHalFactory(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool); + virtual ~WifiLegacyHalFactory() = default; + + std::vector<std::shared_ptr<WifiLegacyHal>> getHals(); + + private: + typedef struct { + wifi_hal_fn fn; + bool primary; + void* handle; + } wifi_hal_lib_desc; + + bool initVendorHalDescriptorFromLinked(); + void initVendorHalsDescriptorList(); + bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn); + bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc); + + std::weak_ptr<wifi_system::InterfaceTool> iface_tool_; + std::vector<wifi_hal_lib_desc> descs_; + std::vector<std::shared_ptr<WifiLegacyHal>> legacy_hals_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_FACTORY_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp new file mode 100644 index 0000000..8f8527a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp @@ -0,0 +1,178 @@ +/* + * 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_6 { +namespace implementation { +namespace legacy_hal { +template <typename> +struct stubFunction; + +template <typename R, typename... Args> +struct stubFunction<R (*)(Args...)> { + static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; } +}; +template <typename... Args> +struct stubFunction<void (*)(Args...)> { + static constexpr void invoke(Args...) {} +}; + +template <typename T> +void populateStubFor(T* val) { + *val = &stubFunction<T>::invoke; +} + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { + if (hal_fn == nullptr) { + return false; + } + populateStubFor(&hal_fn->wifi_initialize); + populateStubFor(&hal_fn->wifi_wait_for_driver_ready); + 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_read_packet_filter); + populateStubFor(&hal_fn->wifi_get_roaming_capabilities); + populateStubFor(&hal_fn->wifi_enable_firmware_roaming); + populateStubFor(&hal_fn->wifi_configure_roaming); + populateStubFor(&hal_fn->wifi_select_tx_power_scenario); + populateStubFor(&hal_fn->wifi_reset_tx_power_scenario); + populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler); + populateStubFor(&hal_fn->wifi_set_latency_mode); + populateStubFor(&hal_fn->wifi_set_thermal_mitigation_mode); + populateStubFor(&hal_fn->wifi_virtual_interface_create); + populateStubFor(&hal_fn->wifi_virtual_interface_delete); + populateStubFor(&hal_fn->wifi_map_dscp_access_category); + populateStubFor(&hal_fn->wifi_reset_dscp_mapping); + populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler); + populateStubFor(&hal_fn->wifi_get_supported_iface_name); + populateStubFor(&hal_fn->wifi_early_initialize); + populateStubFor(&hal_fn->wifi_get_chip_feature_set); + populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection); + populateStubFor(&hal_fn->wifi_multi_sta_set_use_case); + populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels); + populateStubFor(&hal_fn->wifi_set_voip_mode); + populateStubFor(&hal_fn->wifi_twt_register_handler); + populateStubFor(&hal_fn->wifi_twt_get_capability); + populateStubFor(&hal_fn->wifi_twt_setup_request); + populateStubFor(&hal_fn->wifi_twt_teardown_request); + populateStubFor(&hal_fn->wifi_twt_info_frame_request); + populateStubFor(&hal_fn->wifi_twt_get_stats); + populateStubFor(&hal_fn->wifi_twt_clear_stats); + populateStubFor(&hal_fn->wifi_set_dtim_config); + populateStubFor(&hal_fn->wifi_get_usable_channels); + populateStubFor(&hal_fn->wifi_trigger_subsystem_restart); + populateStubFor(&hal_fn->wifi_set_indoor_state); + populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix); + populateStubFor(&hal_fn->wifi_nan_rtt_chre_enable_request); + populateStubFor(&hal_fn->wifi_nan_rtt_chre_disable_request); + populateStubFor(&hal_fn->wifi_chre_register_handler); + populateStubFor(&hal_fn->wifi_enable_tx_power_limits); + populateStubFor(&hal_fn->wifi_get_cached_scan_results); + return true; +} +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h new file mode 100644 index 0000000..ebc0347 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.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 WIFI_LEGACY_HAL_STUBS_H_ +#define WIFI_LEGACY_HAL_STUBS_H_ + +#include <hal_legacy/wifi_hal.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_STUBS_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp new file mode 100644 index 0000000..4b8ac7d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp @@ -0,0 +1,89 @@ +/* + * 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <private/android_filesystem_config.h> + +#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 + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace mode_controller { + +WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {} + +bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) { + return driver_tool_->IsFirmwareModeChangeNeeded(convertIfaceTypeToFirmwareMode(type)); +} + +bool WifiModeController::initialize() { + if (!driver_tool_->LoadDriver()) { + LOG(ERROR) << "Failed to load WiFi driver"; + return false; + } + return true; +} + +bool WifiModeController::changeFirmwareMode(IfaceType type) { + 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_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h new file mode 100644 index 0000000..fee2b66 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h @@ -0,0 +1,63 @@ +/* + * 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 <wifi_hal/driver_tool.h> + +#include <android/hardware/wifi/1.0/IWifi.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +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(); + virtual ~WifiModeController() = default; + + // Checks if a firmware mode change is necessary to support the specified + // iface type operations. + virtual bool isFirmwareModeChangeNeeded(IfaceType type); + virtual bool initialize(); + // Change the firmware mode to support the specified iface type operations. + virtual bool changeFirmwareMode(IfaceType type); + // Unload the driver. This should be invoked whenever |IWifi.stop()| is + // invoked. + virtual bool deinitialize(); + + private: + std::unique_ptr<wifi_hal::DriverTool> driver_tool_; +}; + +} // namespace mode_controller +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_MODE_CONTROLLER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp new file mode 100644 index 0000000..4c61ba7 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp @@ -0,0 +1,1018 @@ +/* + * 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 <android-base/logging.h> + +#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_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiNanIface::WifiNanIface(const std::string& ifname, bool is_dedicated_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) + : ifname_(ifname), + is_dedicated_iface_(is_dedicated_iface), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { + if (is_dedicated_iface_) { + // If using a dedicated iface, set the iface up first. + if (!iface_util_.lock()->setUpState(ifname_, true)) { + // Fatal failure, invalidate the iface object. + invalidate(); + return; + } + } + // 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<WifiNanIface> 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: { + V1_6::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_1_6()) { + if (!callback->notifyCapabilitiesResponse_1_6(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; + } + V1_6::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_1_6()) { + if (!callback->eventMatch_1_6(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; + } + V1_6::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_1_6()) { + if (!callback->eventDataPathConfirm_1_6(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"; + }; + + callback_handlers.on_event_schedule_update = + [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& 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; + } + V1_6::NanDataPathScheduleUpdateInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) { + if (!callback->eventDataPathScheduleUpdate_1_6(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to register nan callbacks. Invalidating object"; + invalidate(); + } + + // Register for iface state toggle events. + iface_util::IfaceEventHandlers event_handlers = {}; +#ifndef WIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN + event_handlers.on_state_toggle_off_on = [weak_ptr_this](const std::string& /* iface_name */) { + 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; + } + // Tell framework that NAN has been disabled. + WifiNanStatus status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; +#endif + iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers); +} + +void WifiNanIface::invalidate() { + if (!isValid()) { + return; + } + // send commands to HAL to actually disable and destroy interfaces + legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0"); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1"); + iface_util_.lock()->unregisterIfaceEventHandlers(ifname_); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + event_cb_handler_1_2_.invalidate(); + event_cb_handler_1_5_.invalidate(); + is_valid_ = false; + if (is_dedicated_iface_) { + // If using a dedicated iface, set the iface down. + iface_util_.lock()->setUpState(ifname_, false); + } +} + +bool WifiNanIface::isValid() { + return is_valid_; +} + +std::string WifiNanIface::getName() { + return ifname_; +} + +std::set<sp<V1_0::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +std::set<sp<V1_2::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_2() { + return event_cb_handler_1_2_.getCallbacks(); +} + +std::set<sp<V1_5::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_5() { + return event_cb_handler_1_5_.getCallbacks(); +} + +std::set<sp<V1_6::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_6() { + return event_cb_handler_1_6_.getCallbacks(); +} + +Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiNanIface::registerEventCallback( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallbackInternal, hidl_status_cb, callback); +} + +Return<void> 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<void> WifiNanIface::enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + configRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return<void> 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<void> WifiNanIface::startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return<void> 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<void> WifiNanIface::startSubscribeRequest(uint16_t cmd_id, + const V1_0::NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startSubscribeRequestInternal, hidl_status_cb, cmd_id, + msg); +} + +Return<void> 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<void> 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<void> 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<void> 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<void> WifiNanIface::initiateDataPathRequest(uint16_t cmd_id, + const V1_0::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequestInternal, hidl_status_cb, cmd_id, + msg); +} + +Return<void> WifiNanIface::respondToDataPathIndicationRequest( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> 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); +} + +Return<void> WifiNanIface::registerEventCallback_1_2( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_2Internal, hidl_status_cb, + callback); +} + +Return<void> WifiNanIface::enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_2Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_2Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_4Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_4Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::registerEventCallback_1_5( + const sp<V1_5::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_5Internal, hidl_status_cb, + callback); +} + +Return<void> WifiNanIface::enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_5Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_5Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::getCapabilitiesRequest_1_5( + uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequest_1_5Internal, hidl_status_cb, + cmd_id); +} + +Return<void> WifiNanIface::enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_6Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_6Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return<void> WifiNanIface::initiateDataPathRequest_1_6(uint16_t cmd_id, + const V1_6::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequest_1_6Internal, hidl_status_cb, + cmd_id, msg); +} + +Return<void> WifiNanIface::respondToDataPathIndicationRequest_1_6( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequest_1_6Internal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::startPublishRequest_1_6(uint16_t cmd_id, + const V1_6::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequest_1_6Internal, hidl_status_cb, cmd_id, + msg); +} + +std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN}; +} + +Return<void> WifiNanIface::registerEventCallback_1_6( + const sp<V1_6::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_6Internal, hidl_status_cb, + callback); +} + +WifiStatus WifiNanIface::registerEventCallbackInternal( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanEnableRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanConfigRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanPublishRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +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(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startSubscribeRequestInternal(uint16_t cmd_id, + const V1_0::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(ifname_, 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(ifname_, 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(ifname_, 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(ifname_, 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(ifname_, cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::initiateDataPathRequestInternal( + uint16_t cmd_id, const V1_0::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(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const V1_0::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(ifname_, 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(ifname_, cmd_id, ndpInstanceId); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::registerEventCallback_1_2Internal( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback) { + sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_2_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::enableRequest_1_2Internal( + uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_2Internal( + uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequest_1_4Internal( + uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_4Internal( + uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::registerEventCallback_1_5Internal( + const sp<V1_5::IWifiNanIfaceEventCallback>& callback) { + sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback; + if (!event_cb_handler_1_2_.addCallback(callback_1_2)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_5_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::enableRequest_1_5Internal( + uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */, + const V1_5::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_5Internal( + uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */, + const V1_5::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequest_1_6Internal(uint16_t cmd_id, + const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanEnableRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanEnableRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::configRequest_1_6Internal(uint16_t cmd_id, + const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanConfigRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanConfigRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::initiateDataPathRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg) { + legacy_hal::NanDataPathInitiatorRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequest_1_6ToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::respondToDataPathIndicationRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg) { + legacy_hal::NanDataPathIndicationResponse legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathIndicationResponse_1_6ToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequest_1_6Internal(uint16_t cmd_id, + const V1_6::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(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::registerEventCallback_1_6Internal( + const sp<V1_6::IWifiNanIfaceEventCallback>& callback) { + sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback; + if (!event_cb_handler_1_2_.addCallback(callback_1_2)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp<V1_5::IWifiNanIfaceEventCallback> callback_1_5 = callback; + if (!event_cb_handler_1_5_.addCallback(callback_1_5)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_6_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h new file mode 100644 index 0000000..15bf572 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h @@ -0,0 +1,208 @@ +/* + * 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 <android-base/macros.h> +#include <android/hardware/wifi/1.6/IWifiNanIface.h> +#include <android/hardware/wifi/1.6/IWifiNanIfaceEventCallback.h> + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; +using namespace android::hardware::wifi::V1_2; +using namespace android::hardware::wifi::V1_4; +using namespace android::hardware::wifi::V1_6; + +/** + * HIDL interface object used to control a NAN Iface instance. + */ +class WifiNanIface : public V1_6::IWifiNanIface { + public: + WifiNanIface(const std::string& ifname, bool is_dedicated_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> registerEventCallback(const sp<V1_0::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilitiesRequest(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) override; + Return<void> enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) override; + Return<void> configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + configRequest_cb hidl_status_cb) override; + Return<void> disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) override; + Return<void> startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + Return<void> stopPublishRequest(uint16_t cmd_id, uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) override; + Return<void> startSubscribeRequest(uint16_t cmd_id, const V1_0::NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) override; + Return<void> stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) override; + Return<void> transmitFollowupRequest(uint16_t cmd_id, const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) override; + Return<void> createDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) override; + Return<void> deleteDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) override; + Return<void> initiateDataPathRequest(uint16_t cmd_id, + const V1_0::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) override; + Return<void> respondToDataPathIndicationRequest( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) override; + Return<void> terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) override; + + Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return<void> enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) override; + Return<void> configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) override; + Return<void> enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_4_cb hidl_status_cb) override; + Return<void> configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_4_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_5_cb hidl_status_cb) override; + Return<void> enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) override; + Return<void> configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) override; + Return<void> getCapabilitiesRequest_1_5(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_6(const sp<V1_6::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_6_cb hidl_status_cb) override; + Return<void> initiateDataPathRequest_1_6( + uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_1_6_cb hidl_status_cb) override; + Return<void> respondToDataPathIndicationRequest_1_6( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_1_6_cb hidl_status_cb) override; + Return<void> enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + enableRequest_1_6_cb hidl_status_cb) override; + Return<void> configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + configRequest_1_6_cb hidl_status_cb) override; + Return<void> startPublishRequest_1_6(uint16_t cmd_id, const V1_6::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus registerEventCallbackInternal(const sp<V1_0::IWifiNanIfaceEventCallback>& callback); + WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id); + WifiStatus enableRequestInternal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg); + WifiStatus configRequestInternal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg); + WifiStatus disableRequestInternal(uint16_t cmd_id); + WifiStatus startPublishRequestInternal(uint16_t cmd_id, const V1_0::NanPublishRequest& msg); + WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, const V1_0::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 V1_0::NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg); + WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId); + + WifiStatus registerEventCallback_1_2Internal( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback); + WifiStatus enableRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus enableRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus registerEventCallback_1_5Internal( + const sp<V1_5::IWifiNanIfaceEventCallback>& callback); + WifiStatus enableRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_5::NanConfigRequestSupplemental& msg2); + WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id); + WifiStatus registerEventCallback_1_6Internal( + const sp<V1_6::IWifiNanIfaceEventCallback>& callback); + + WifiStatus enableRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_6::NanConfigRequestSupplemental& msg2); + WifiStatus startPublishRequest_1_6Internal(uint16_t cmd_id, const V1_6::NanPublishRequest& msg); + WifiStatus initiateDataPathRequest_1_6Internal(uint16_t cmd_id, + const V1_6::NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg); + + // all 1_0 and descendant callbacks + std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks(); + // all 1_2 and descendant callbacks + std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2(); + // all 1_5 and descendant callbacks + std::set<sp<V1_5::IWifiNanIfaceEventCallback>> getEventCallbacks_1_5(); + // all 1_6 and descendant callbacks + std::set<sp<V1_6::IWifiNanIfaceEventCallback>> getEventCallbacks_1_6(); + + std::string ifname_; + bool is_dedicated_iface_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback> event_cb_handler_; + hidl_callback_util::HidlCallbackHandler<V1_2::IWifiNanIfaceEventCallback> event_cb_handler_1_2_; + hidl_callback_util::HidlCallbackHandler<V1_5::IWifiNanIfaceEventCallback> event_cb_handler_1_5_; + hidl_callback_util::HidlCallbackHandler<V1_6::IWifiNanIfaceEventCallback> event_cb_handler_1_6_; + + DISALLOW_COPY_AND_ASSIGN(WifiNanIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_NAN_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp new file mode 100644 index 0000000..d4b1fca --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp @@ -0,0 +1,69 @@ +/* + * 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 <android-base/logging.h> + +#include "hidl_return_util.h" +#include "wifi_p2p_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiP2pIface::WifiP2pIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> 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_; +} + +std::string WifiP2pIface::getName() { + return ifname_; +} + +Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiP2pIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getTypeInternal, hidl_status_cb); +} + +std::pair<WifiStatus, std::string> WifiP2pIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiP2pIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P}; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h new file mode 100644 index 0000000..0089443 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h @@ -0,0 +1,66 @@ +/* + * 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 <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiP2pIface.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +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::WifiLegacyHal> legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiP2pIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_P2P_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp new file mode 100644 index 0000000..aa9ee2f --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp @@ -0,0 +1,377 @@ +/* + * 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 <android-base/logging.h> + +#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_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiRttController::WifiRttController(const std::string& iface_name, + const sp<IWifiIface>& bound_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal) + : ifname_(iface_name), 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<sp<V1_6::IWifiRttControllerEventCallback>> WifiRttController::getEventCallbacks() { + return event_callbacks_; +} + +std::string WifiRttController::getIfaceName() { + return ifname_; +} + +Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getBoundIfaceInternal, hidl_status_cb); +} + +Return<void> WifiRttController::registerEventCallback( + const sp<V1_0::IWifiRttControllerEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal, hidl_status_cb, + callback); +} + +Return<void> WifiRttController::rangeRequest(uint32_t cmd_id, + const hidl_vec<V1_0::RttConfig>& 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<void> WifiRttController::rangeCancel(uint32_t cmd_id, + const hidl_vec<hidl_array<uint8_t, 6>>& addrs, + rangeCancel_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs); +} + +Return<void> WifiRttController::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiRttController::getResponderInfo(getResponderInfo_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal, hidl_status_cb); +} + +Return<void> WifiRttController::enableResponder(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_0::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<void> 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); +} + +Return<void> WifiRttController::registerEventCallback_1_4( + const sp<V1_4::IWifiRttControllerEventCallback>& callback, + registerEventCallback_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal_1_4, hidl_status_cb, + callback); +} + +Return<void> WifiRttController::rangeRequest_1_4(uint32_t cmd_id, + const hidl_vec<V1_4::RttConfig>& rtt_configs, + rangeRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal_1_4, hidl_status_cb, cmd_id, + rtt_configs); +} + +Return<void> WifiRttController::getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal_1_4, hidl_status_cb); +} + +Return<void> WifiRttController::getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal_1_4, hidl_status_cb); +} + +Return<void> WifiRttController::enableResponder_1_4(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_4::RttResponder& info, + enableResponder_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal_1_4, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +Return<void> WifiRttController::registerEventCallback_1_6( + const sp<V1_6::IWifiRttControllerEventCallback>& callback, + registerEventCallback_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal_1_6, hidl_status_cb, + callback); +} + +Return<void> WifiRttController::rangeRequest_1_6(uint32_t cmd_id, + const hidl_vec<V1_6::RttConfig>& rtt_configs, + rangeRequest_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal_1_6, hidl_status_cb, cmd_id, + rtt_configs); +} + +Return<void> WifiRttController::getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal_1_6, hidl_status_cb); +} + +Return<void> WifiRttController::getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal_1_6, hidl_status_cb); +} + +Return<void> WifiRttController::enableResponder_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::RttResponder& info, + enableResponder_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal_1_6, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +std::pair<WifiStatus, sp<IWifiIface>> WifiRttController::getBoundIfaceInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal( + const sp<V1_0::IWifiRttControllerEventCallback>& /* callback */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeRequestInternal( + uint32_t /* cmd_id */, const std::vector<V1_0::RttConfig>& /* rtt_configs */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeCancelInternal( + uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) { + std::vector<std::array<uint8_t, 6>> legacy_addrs; + for (const auto& addr : addrs) { + legacy_addrs.push_back(addr); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, legacy_addrs); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, V1_0::RttCapabilities> WifiRttController::getCapabilitiesInternal() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +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(ifname_, 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(ifname_, cmd_id, legacy_lcr); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, V1_0::RttResponder> WifiRttController::getResponderInfoInternal() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiRttController::enableResponderInternal( + uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */, + uint32_t /* max_duration_seconds */, const V1_0::RttResponder& /* info */) { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)}; +} + +WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::registerEventCallbackInternal_1_4( + const sp<V1_4::IWifiRttControllerEventCallback>& /* callback */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeRequestInternal_1_4( + uint32_t /* cmd_id */, const std::vector<V1_4::RttConfig>& /* rtt_configs */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +std::pair<WifiStatus, V1_4::RttCapabilities> WifiRttController::getCapabilitiesInternal_1_4() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, V1_4::RttResponder> WifiRttController::getResponderInfoInternal_1_4() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiRttController::enableResponderInternal_1_4( + uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */, + uint32_t /* max_duration_seconds */, const V1_4::RttResponder& /* info */) { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal_1_6( + const sp<V1_6::IWifiRttControllerEventCallback>& callback) { + // TODO(b/31632518): remove the callback when the client is destroyed + event_callbacks_.emplace_back(callback); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiRttController::rangeRequestInternal_1_6( + uint32_t cmd_id, const std::vector<V1_6::RttConfig>& rtt_configs) { + std::vector<legacy_hal::wifi_rtt_config> legacy_configs; + if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp<WifiRttController> weak_ptr_this(this); + const auto& on_results_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id, + const std::vector<const legacy_hal::wifi_rtt_result*>& 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<V1_6::RttResult> 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()) { + if (!callback->onResults_1_6(id, hidl_results).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest( + ifname_, cmd_id, legacy_configs, on_results_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, V1_6::RttCapabilities> WifiRttController::getCapabilitiesInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::RttCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair<WifiStatus, V1_6::RttResponder> WifiRttController::getResponderInfoInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_responder legacy_responder; + std::tie(legacy_status, legacy_responder) = legacy_hal_.lock()->getRttResponderInfo(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::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_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::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( + ifname_, cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder); + return createWifiStatusFromLegacyError(legacy_status); +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h new file mode 100644 index 0000000..fd5f68b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h @@ -0,0 +1,138 @@ +/* + * 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 <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiIface.h> +#include <android/hardware/wifi/1.6/IWifiRttController.h> +#include <android/hardware/wifi/1.6/IWifiRttControllerEventCallback.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * HIDL interface object used to control all RTT operations. + */ +class WifiRttController : public V1_6::IWifiRttController { + public: + WifiRttController(const std::string& iface_name, const sp<IWifiIface>& bound_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::vector<sp<V1_6::IWifiRttControllerEventCallback>> getEventCallbacks(); + std::string getIfaceName(); + + // HIDL methods exposed. + Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override; + Return<void> registerEventCallback(const sp<V1_0::IWifiRttControllerEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> rangeRequest(uint32_t cmd_id, const hidl_vec<V1_0::RttConfig>& rtt_configs, + rangeRequest_cb hidl_status_cb) override; + Return<void> rangeCancel(uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs, + rangeCancel_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci, + setLci_cb hidl_status_cb) override; + Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) override; + Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override; + Return<void> enableResponder(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_0::RttResponder& info, + enableResponder_cb hidl_status_cb) override; + Return<void> disableResponder(uint32_t cmd_id, disableResponder_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_4( + const sp<V1_4::IWifiRttControllerEventCallback>& callback, + registerEventCallback_1_4_cb hidl_status_cb) override; + Return<void> rangeRequest_1_4(uint32_t cmd_id, const hidl_vec<V1_4::RttConfig>& rtt_configs, + rangeRequest_1_4_cb hidl_status_cb) override; + Return<void> getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) override; + Return<void> getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) override; + Return<void> enableResponder_1_4(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_4::RttResponder& info, + enableResponder_1_4_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_6( + const sp<V1_6::IWifiRttControllerEventCallback>& callback, + registerEventCallback_1_6_cb hidl_status_cb) override; + Return<void> rangeRequest_1_6(uint32_t cmd_id, const hidl_vec<V1_6::RttConfig>& rtt_configs, + rangeRequest_1_6_cb hidl_status_cb) override; + Return<void> getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) override; + Return<void> getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) override; + Return<void> enableResponder_1_6(uint32_t cmd_id, const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_6::RttResponder& info, + enableResponder_1_6_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal(); + WifiStatus registerEventCallbackInternal( + const sp<V1_0::IWifiRttControllerEventCallback>& callback); + WifiStatus rangeRequestInternal(uint32_t cmd_id, + const std::vector<V1_0::RttConfig>& rtt_configs); + WifiStatus rangeCancelInternal(uint32_t cmd_id, + const std::vector<hidl_array<uint8_t, 6>>& addrs); + std::pair<WifiStatus, V1_0::RttCapabilities> getCapabilitiesInternal(); + WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci); + WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr); + std::pair<WifiStatus, V1_0::RttResponder> getResponderInfoInternal(); + WifiStatus enableResponderInternal(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_0::RttResponder& info); + WifiStatus disableResponderInternal(uint32_t cmd_id); + WifiStatus registerEventCallbackInternal_1_4( + const sp<V1_4::IWifiRttControllerEventCallback>& callback); + WifiStatus rangeRequestInternal_1_4(uint32_t cmd_id, + const std::vector<V1_4::RttConfig>& rtt_configs); + std::pair<WifiStatus, V1_4::RttCapabilities> getCapabilitiesInternal_1_4(); + std::pair<WifiStatus, V1_4::RttResponder> getResponderInfoInternal_1_4(); + WifiStatus enableResponderInternal_1_4(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_4::RttResponder& info); + WifiStatus registerEventCallbackInternal_1_6( + const sp<V1_6::IWifiRttControllerEventCallback>& callback); + WifiStatus rangeRequestInternal_1_6(uint32_t cmd_id, + const std::vector<V1_6::RttConfig>& rtt_configs); + std::pair<WifiStatus, V1_6::RttCapabilities> getCapabilitiesInternal_1_6(); + std::pair<WifiStatus, V1_6::RttResponder> getResponderInfoInternal_1_6(); + WifiStatus enableResponderInternal_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::RttResponder& info); + + std::string ifname_; + sp<IWifiIface> bound_iface_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::vector<sp<V1_6::IWifiRttControllerEventCallback>> event_callbacks_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiRttController); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_RTT_CONTROLLER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp new file mode 100644 index 0000000..dd11839 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp @@ -0,0 +1,592 @@ +/* + * 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 <android-base/logging.h> + +#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_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiStaIface::WifiStaIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) + : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) { + // Turn on DFS channel usage for STA iface. + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, 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::string WifiStaIface::getName() { + return ifname_; +} + +std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::registerEventCallbackInternal, hidl_status_cb, callback); +} + +Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program, + installApfPacketFilter_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::installApfPacketFilterInternal, hidl_status_cb, cmd_id, + program); +} + +Return<void> WifiStaIface::readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::readApfPacketFilterDataInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getBackgroundScanCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getValidFrequenciesForBand( + V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getValidFrequenciesForBandInternal, hidl_status_cb, band); +} + +Return<void> 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<void> 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<void> WifiStaIface::enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb, + debug); +} + +Return<void> WifiStaIface::disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_3, hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_5, hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_6, hidl_status_cb); +} + +Return<void> 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<void> 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<void> WifiStaIface::getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getRoamingCapabilitiesInternal, hidl_status_cb); +} + +Return<void> 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<void> WifiStaIface::setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setRoamingStateInternal, hidl_status_cb, state); +} + +Return<void> WifiStaIface::enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableNdOffloadInternal, hidl_status_cb, enable); +} + +Return<void> WifiStaIface::startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type, + const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& 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<void> 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<void> WifiStaIface::setScanningMacOui(const hidl_array<uint8_t, 3>& oui, + setScanningMacOui_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanningMacOuiInternal, hidl_status_cb, oui); +} + +Return<void> WifiStaIface::startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugTxPacketFatesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugRxPacketFatesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setMacAddressInternal, hidl_status_cb, mac); +} + +Return<void> WifiStaIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getFactoryMacAddressInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::setScanMode(bool enable, setScanMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanModeInternal, hidl_status_cb, enable); +} + +std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA}; +} + +WifiStatus WifiStaIface::registerEventCallbackInternal( + const sp<IWifiStaIfaceEventCallback>& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname_); + 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(ifname_); + 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<WifiStatus, StaApfPacketFilterCapabilities> +WifiStaIface::getApfPacketFilterCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::PacketFilterCapabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getPacketFilterCapabilities(ifname_); + 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<uint8_t>& program) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setPacketFilter(ifname_, program); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<uint8_t>> WifiStaIface::readApfPacketFilterDataInternal() { + const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>> legacy_status_and_data = + legacy_hal_.lock()->readApfPacketFilterData(ifname_); + return {createWifiStatusFromLegacyError(legacy_status_and_data.first), + std::move(legacy_status_and_data.second)}; +} + +std::pair<WifiStatus, StaBackgroundScanCapabilities> +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(ifname_); + 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<WifiStatus, std::vector<WifiChannelInMhz>> +WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector<uint32_t> valid_frequencies; + std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand( + ifname_, 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<WifiStaIface> 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<legacy_hal::wifi_cached_scan_results>& 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<StaScanData> 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(ifname_, 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(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableLinkLayerStats(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, V1_0::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, V1_3::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_3() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, V1_5::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_5() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, V1_6::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::LinkLayerStats legacy_stats; + std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::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<WifiStaIface> weak_ptr_this(this); + const auto& on_threshold_breached_callback = [weak_ptr_this](legacy_hal::wifi_request_id id, + std::array<uint8_t, 6> 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( + ifname_, 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(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, StaRoamingCapabilities> 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(ifname_); + 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(ifname_, legacy_config); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableFirmwareRoaming( + ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->configureNdOffload(ifname_, enable); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, uint16_t ether_type, + const std::array<uint8_t, 6>& src_address, const std::array<uint8_t, 6>& dst_address, + uint32_t period_in_ms) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket( + ifname_, cmd_id, ether_type, 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(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setScanningMacOuiInternal(const std::array<uint8_t, 3>& /* oui */) { + // deprecated. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startPktFateMonitoring(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> +WifiStaIface::getDebugTxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_tx_report> legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugTxPacketFateReport> hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(legacy_fates, + &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> +WifiStaIface::getDebugRxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_rx_report> legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugRxPacketFateReport> hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(legacy_fates, + &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +WifiStatus WifiStaIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) { + bool status = iface_util_.lock()->setMacAddress(ifname_, mac); + if (!status) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, std::array<uint8_t, 6>> WifiStaIface::getFactoryMacAddressInternal() { + std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifname_); + if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; +} + +WifiStatus WifiStaIface::setScanModeInternal(bool enable) { + // OEM's need to implement this on their devices if needed. + LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported"; + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h new file mode 100644 index 0000000..c01c50b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h @@ -0,0 +1,157 @@ +/* + * 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 <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h> +#include <android/hardware/wifi/1.6/IWifiStaIface.h> + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a STA Iface instance. + */ +class WifiStaIface : public V1_6::IWifiStaIface { + public: + WifiStaIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) override; + Return<void> installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program, + installApfPacketFilter_cb hidl_status_cb) override; + Return<void> readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) override; + Return<void> getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) override; + Return<void> getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) override; + Return<void> startBackgroundScan(uint32_t cmd_id, const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) override; + Return<void> stopBackgroundScan(uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override; + Return<void> enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return<void> disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return<void> getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override; + Return<void> getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) override; + Return<void> getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) override; + Return<void> getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) override; + Return<void> startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) override; + Return<void> stopRssiMonitoring(uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override; + Return<void> getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) override; + Return<void> configureRoaming(const StaRoamingConfig& config, + configureRoaming_cb hidl_status_cb) override; + Return<void> setRoamingState(StaRoamingState state, setRoamingState_cb hidl_status_cb) override; + Return<void> enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) override; + Return<void> startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type, + const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& dst_address, + uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) override; + Return<void> stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override; + Return<void> setScanningMacOui(const hidl_array<uint8_t, 3>& oui, + setScanningMacOui_cb hidl_status_cb) override; + Return<void> startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) override; + Return<void> getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) override; + Return<void> getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) override; + Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) override; + Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override; + Return<void> setScanMode(bool enable, setScanMode_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus registerEventCallbackInternal(const sp<IWifiStaIfaceEventCallback>& callback); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal(); + std::pair<WifiStatus, StaApfPacketFilterCapabilities> getApfPacketFilterCapabilitiesInternal(); + WifiStatus installApfPacketFilterInternal(uint32_t cmd_id, const std::vector<uint8_t>& program); + std::pair<WifiStatus, std::vector<uint8_t>> readApfPacketFilterDataInternal(); + std::pair<WifiStatus, StaBackgroundScanCapabilities> getBackgroundScanCapabilitiesInternal(); + std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal( + V1_0::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<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal(); + std::pair<WifiStatus, V1_3::StaLinkLayerStats> getLinkLayerStatsInternal_1_3(); + std::pair<WifiStatus, V1_5::StaLinkLayerStats> getLinkLayerStatsInternal_1_5(); + std::pair<WifiStatus, V1_6::StaLinkLayerStats> getLinkLayerStatsInternal_1_6(); + WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi); + WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); + std::pair<WifiStatus, StaRoamingCapabilities> getRoamingCapabilitiesInternal(); + WifiStatus configureRoamingInternal(const StaRoamingConfig& config); + WifiStatus setRoamingStateInternal(StaRoamingState state); + WifiStatus enableNdOffloadInternal(bool enable); + WifiStatus startSendingKeepAlivePacketsInternal(uint32_t cmd_id, + const std::vector<uint8_t>& ip_packet_data, + uint16_t ether_type, + const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, + uint32_t period_in_ms); + WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id); + WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui); + WifiStatus startDebugPacketFateMonitoringInternal(); + std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> getDebugTxPacketFatesInternal(); + std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> getDebugRxPacketFatesInternal(); + WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac); + std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal(); + WifiStatus setScanModeInternal(bool enable); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback> event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiStaIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STA_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp new file mode 100644 index 0000000..3b18e53 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/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_6 { +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"; + default: + return "UNKNOWN ERROR"; + } +} + +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"); + + default: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown error"); + } +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { + return createWifiStatusFromLegacyError(error, ""); +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h new file mode 100644 index 0000000..ea1c294 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h @@ -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. + */ + +#ifndef WIFI_STATUS_UTIL_H_ +#define WIFI_STATUS_UTIL_H_ + +#include <android/hardware/wifi/1.4/IWifi.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +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_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STATUS_UTIL_H_ |