/*
 * Copyright 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.
 */

package android.hardware.wifi@1.5;

import @1.0::WifiStatus;
import @1.5::IWifiApIface;
import @1.0::IWifiIface;
import @1.3::IWifiChip;
import @1.4::IWifiChip;

/**
 * Interface that represents a chip that must be configured as a single unit.
 */
interface IWifiChip extends @1.4::IWifiChip {
    /**
     * Capabilities exposed by this chip.
     */
    enum ChipCapabilityMask : @1.3::IWifiChip.ChipCapabilityMask {
        /**
         * chip can operate in the 60GHz band(WiGig chip)
         */
        WIGIG = 1 << 14,
    };

    /**
     * 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.
     *   - When there is only 1 STA interface, the must should still retain the last use case
     *     set, which must become active the next time multi STA is enabled.
     *     1. Initialize with single STA.
     *     2. Framework creates second STA.
     *     3. Framework sets use case to DUAL_STA_NON_TRANSIENT_UNBIASED.
     *     4. Framework destroys second STA. Only 1 STA remains.
     *     5. Framework recreates second STA.
     *     6. The active use case remains DUAL_STA_NON_TRANSIENT_UNBIASED (i.e. firmware should not
     *        automatically change it during period of single STA unless requested by framework).
     */
    enum MultiStaUseCase : uint8_t {
        /**
         * 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.
         */
        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.
         */
        DUAL_STA_NON_TRANSIENT_UNBIASED = 1,
    };

    /**
     * Get the capabilities supported by this chip.
     *
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
     *         |WifiStatusCode.ERROR_UNKNOWN|
     * @return capabilities Bitset of |ChipCapabilityMask| values.
     */
    getCapabilities_1_5()
        generates (WifiStatus status, bitfield<ChipCapabilityMask> capabilities);

    /**
     * Invoked to indicate that the provided iface is the primary STA iface when there are more
     * than 1 STA iface concurrently active.
     * Notes:
     * - 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.
     * - When there is only 1 STA interface, the firmware must still retain the last primary
     *   connection, which must become active the next time multi STA is enabled.
     *
     * @param ifname Name of the STA iface.
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_INVALID_ARGS|
     */
    setMultiStaPrimaryConnection(string ifName) generates (WifiStatus status);

    /**
     * Invoked to indicate the STA + STA use-case that is active.
     *
     * Refer to documentation of |MultiStaUseCase| for details.
     *
     * @param useCase Use case that is active.
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_INVALID_ARGS|
     */
    setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);

    /**
     * Create bridged IWifiApIface.
     *
     * Depending on the mode the chip is configured in, the interface creation
     * may fail (code: |ERROR_NOT_AVAILABLE|) if we've already reached the maximum
     * allowed (specified in |ChipIfaceCombination|) number of ifaces of the AP
     * type.
     *
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
     * @return iface HIDL interface object representing the iface if
     *         successful, null otherwise.
     */
    createBridgedApIface() generates (WifiStatus status, IWifiApIface iface);

    /**
     * Removes one of the instance on the AP Iface with the provided ifaceName and
     * ifaceInstanceName.
     *
     * Use the API: removeApIface with brIfaceName in the V1_0::WifiChip.hal to remove bridge Iface.
     *
     * @param brIfaceName Name of the bridged AP iface.
     * @param ifaceInstanceName Name of the instance. The empty instance is
     * invalid.
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
     */
    removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName)
        generates (WifiStatus status);

    /**
     * Representation of a Wi-Fi channel for Wi-Fi coex channel avoidance.
     */
    struct CoexUnsafeChannel {
        /* The band of the channel */
        WifiBand band;
        /* The channel number */
        uint32_t channel;
        /** The power cap will be a maximum power value in dbm that is allowed to be transmitted by
            the chip on this channel. A value of PowerCapConstant.NO_POWER_CAP means no limitation
            on transmitted power is needed by the chip for this channel.
        */
        int32_t powerCapDbm;
    };

    enum PowerCapConstant : int32_t {
        NO_POWER_CAP = 0x7FFFFFFF,
    };

    enum CoexRestriction : uint32_t {
        WIFI_DIRECT = 1 << 0,
        SOFTAP = 1 << 1,
        WIFI_AWARE = 1 << 2
    };

    /**
     * Invoked to indicate that the provided |CoexUnsafeChannels| should be avoided with the
     * specified restrictions.
     *
     * Channel avoidance is a suggestion and should be done on a best-effort approach. If a provided
     * channel is used, then the specified power cap should be applied.
     *
     * In addition, hard restrictions on the Wifi modes may be indicated by |CoexRestriction| bits
     * (WIFI_DIRECT, SOFTAP, WIFI_AWARE) in the |restrictions| bitfield. If a hard restriction is
     * provided, then the channels should be completely avoided for the provided Wifi modes instead
     * of by best-effort.
     *
     * @param unsafeChannels List of |CoexUnsafeChannels| to avoid.
     * @param restrictions Bitset of |CoexRestriction| values indicating Wifi interfaces to
     *         completely avoid.
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
     */
    setCoexUnsafeChannels(
        vec<CoexUnsafeChannel> unsafeChannels, bitfield<CoexRestriction> restrictions)
            generates (WifiStatus status);

    /**
     * Set country code for this Wifi chip.
     *
     * Country code is global setting across the Wifi chip and not Wifi
     * interface (STA or AP) specific. Legacy HAL API's for country code in
     * @1.0::ISupplicantStaIface::setCountryCode &
     * @1.0::IWifiApIface:setCountryCode are deprecated in favor of this
     * chip level API.
     *
     * @param code 2 byte country code (as defined in ISO 3166) to set.
     * @return status Status of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.FAILURE_UNKNOWN|,
     *         |WifiStatusCode.FAILURE_IFACE_INVALID|
     */
    setCountryCode(int8_t[2] code) generates (WifiStatus status);

    /**
     * Usable Wifi channels filter masks.
     */
    enum UsableChannelFilter : uint32_t {
        /**
         * Filter Wifi channels that should be avoided due to extreme
         * cellular coexistence restrictions. Some Wifi channels can have
         * extreme interference from/to cellular due to short frequency
         * seperation 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.
         */
        CELLULAR_COEXISTENCE = 1 << 0,
        /**
         * Filter based on 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.
         */
        CONCURRENCY = 1 << 1,
    };

    /**
     * Retrieve list of usable Wifi channels for the specified band &
     * operational modes.
     *
     * The list of usable Wifi channels in a given band depends on factors
     * like current country code, operational mode (e.g. STA, SAP, WFD-CLI,
     * WFD-GO, TDLS, NAN) and other restrictons due to DFS, cellular coexistence
     * and conncurency state of the device.
     *
     * @param band |WifiBand| for which list of usable channels is requested.
     * @param ifaceModeMask Bitmask of the modes represented by |WifiIfaceMode|
     *        Bitmask respresents all the modes that the caller is interested
     *        in (e.g. STA, SAP, CLI, GO, TDLS, NAN). E.g. If the caller is
     *        interested in knowing usable channels for P2P CLI, P2P GO & NAN,
     *        ifaceModeMask would be set to
     *        IFACE_MODE_P2P_CLIENT|IFACE_MODE_P2P_GO|IFACE_MODE_NAN.
     * @param filterMask Bitmask of filters represented by
     *        |UsableChannelFilter|. Specifies whether driver should filter
     *        channels based on additional criteria. If no filter is specified
     *        driver should return usable channels purely based on regulatory
     *        constraints.
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
     *         |WifiStatusCode.FAILURE_UNKNOWN|
     * @return channels List of channels represented by |WifiUsableChannel|
     *         Each entry represents a channel frequency, bandwidth and
     *         bitmask of modes (e.g. STA, SAP, CLI, GO, TDLS, NAN) that are
     *         allowed on that channel. E.g. If only STA mode can be supported
     *         on an indoor channel, only the IFACE_MODE_STA bit would be set
     *         for that channel. If 5GHz SAP cannot be supported, then none of
     *         the 5GHz channels will have IFACE_MODE_SOFTAP bit set.
     *         Note: Bits do not represent concurrency state. Each bit only
     *         represents whether particular mode is allowed on that channel.
     */
    getUsableChannels(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask,
            bitfield<UsableChannelFilter> filterMask)
        generates (WifiStatus status, vec<WifiUsableChannel> channels);

    /**
     * Trigger subsystem restart
     *
     * If the framework detects a problem (e.g. connection failure),
     * it must call this function to attempt recovery.
     *
     * When the wifi HAL receiveds triggerSubsystemRestart(), it must restart
     * the wlan subsystem, especially the wlan firmware.
     *
     * Regarding the callback function for subsystem restart, refer to documentation of
     * |IWifiEventCallback.onSubsystemRestart| for details.
     *
     * @return status WifiStatus of the operation.
     *         Possible status codes:
     *         |WifiStatusCode.SUCCESS|,
     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
     *         |WifiStatusCode.ERROR_UNKNOWN|
     */
    triggerSubsystemRestart() generates (WifiStatus status);
};
