blob: fa1f4d6c65c654120af85e5efa9347675f83892a [file] [log] [blame]
/*
* Copyright 2019 The Fuchsia Authors.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// TODO(29700): Consolidate to one ieee80211.h
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_IEEE80211_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_IEEE80211_H_
#include <netinet/if_ether.h>
#include <stddef.h>
#include <stdint.h>
#include "third_party/driver-lib/wlan/ieee80211.h"
#include "third_party/iwlwifi/platform/banjo/ieee80211.h"
#include "third_party/iwlwifi/platform/banjo/softmac.h"
#include "third_party/iwlwifi/platform/compiler.h"
#if defined(__cplusplus)
extern "C" {
#endif // defined(__cplusplus)
// The below constants are not defined in the 802.11-2016 Std.
#define IEEE80211_MAX_CHAINS 4
#define IEEE80211_MAX_RTS_THRESHOLD 2353
#define IEEE80211_MAC_PACKET_HEADROOM_SIZE 8
// Used as the default value in the data structure to indicate the queue is not set yet.
#define IEEE80211_INVAL_HW_QUEUE 0xff
// Convert the TID sequence number into the SSN (start sequence number) in the BAR (Block Ack
// Request).
#define IEEE80211_SCTL_SEQ_MASK 0xfff
#define IEEE80211_SCTL_SEQ_OFFSET 4
#define IEEE80211_SEQ_TO_SN(seq) (((seq) >> IEEE80211_SCTL_SEQ_OFFSET) & IEEE80211_SCTL_SEQ_MASK)
/* 802.11n HT capabilities masks (for cap_info) */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
#define IEEE80211_HT_CAP_RESERVED 0x2000
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
/* 802.11n HT capability MSC set */
#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff
#define IEEE80211_HT_MCS_TX_DEFINED 0x01
#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
/* A-PMDU buffer sizes, which varies from 8KB to 1MB */
#define IEEE80211_MIN_AMPDU_BUF 0x8
#define IEEE80211_MAX_AMPDU_BUF_HT 0x40
#define IEEE80211_MAX_AMPDU_BUF_HE 0x100
#define IEEE80211_MAX_AMPDU_BUF_EHT 0x400
// Ids of information elements referred in this driver.
#define WLAN_EID_SSID 0
// The maximum length for SSID string.
//
// It is equal to fuchsia_wlan_ieee80211::wire::kMaxSsidByteLen, but
// we cannot use C++ syntax because this file is included by c files as well.
#define IEEE80211_MAX_SSID_LEN 32
// The length of PN in the CCMP header.
//
#define IEEE80211_CCMP_PN_LEN (fuchsia_wlan_ieee80211_CCMP_PN_LEN)
// The length for array size.
#define IEEE80211_MAX_PN_LEN 16
// The offset in the TX TKPI key array.
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
// The offset in the RX TKPI key array.
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
// The number of TID.
#define IEEE80211_NUM_TIDS (fuchsia_wlan_ieee80211_TIDS_MAX)
// The order of access categories is not clearly specified in 802.11-2016 Std.
// Therefore it cannot be moved into ieee80211 banjo file.
enum ieee80211_ac_numbers {
IEEE80211_AC_VO = 0,
IEEE80211_AC_VI = 1,
IEEE80211_AC_BE = 2,
IEEE80211_AC_BK = 3,
IEEE80211_AC_MAX = 4,
};
enum ieee80211_frame_release_type {
IEEE80211_FRAME_RELEASE_PSPOLL,
IEEE80211_FRAME_RELEASE_UAPSD,
};
// IEEE Std 802.11-2016, 9.4.2.56.3, Table 9-163
enum ieee80211_max_ampdu_length_exp {
IEEE80211_HT_MAX_AMPDU_8K = 0,
IEEE80211_HT_MAX_AMPDU_16K = 1,
IEEE80211_HT_MAX_AMPDU_32K = 2,
IEEE80211_HT_MAX_AMPDU_64K = 3
};
/* Minimum MPDU start spacing */
enum ieee80211_min_mpdu_spacing {
IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */
IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */
IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */
IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */
IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */
IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */
IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */
IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */
};
enum ieee80211_roc_type {
IEEE80211_ROC_TYPE_NORMAL = 0,
IEEE80211_ROC_TYPE_MGMT_TX,
};
enum ieee80211_rssi_event_data {
RSSI_EVENT_HIGH,
RSSI_EVENT_LOW,
};
enum ieee80211_smps_mode {
IEEE80211_SMPS_AUTOMATIC,
IEEE80211_SMPS_OFF,
IEEE80211_SMPS_STATIC,
IEEE80211_SMPS_DYNAMIC,
IEEE80211_SMPS_NUM_MODES,
};
// NEEDS_PORTING: Below structures are only referenced in function prototype.
// Doesn't need a dummy byte.
struct cfg80211_gtk_rekey_data;
struct cfg80211_nan_conf;
struct cfg80211_nan_func;
struct cfg80211_scan_request;
struct cfg80211_sched_scan_request;
struct cfg80211_wowlan;
struct ieee80211_key_conf;
struct ieee80211_sta_ht_cap;
struct ieee80211_scan_ies;
struct ieee80211_tdls_ch_sw_params;
// NEEDS_PORTING: Below structures are used in code but not ported yet.
// A dummy byte is required to suppress the C++ warning message for empty
// struct.
struct ieee80211_hdr {
char dummy;
};
struct ieee80211_ops {
char dummy;
};
struct ieee80211_p2p_noa_desc {
char dummy;
};
// This is similar with 'wlan_band_t'.
enum nl80211_band {
NL80211_BAND_2GHZ,
NL80211_BAND_5GHZ,
NL80211_BAND_6GHZ,
NUM_NL80211_BANDS,
};
static inline enum nl80211_band convert_wlan_band_to_nl80211_band(wlan_band_t band) {
switch (band) {
case WLAN_BAND_TWO_GHZ:
return NL80211_BAND_2GHZ;
case WLAN_BAND_FIVE_GHZ:
return NL80211_BAND_5GHZ;
default:
return NUM_NL80211_BANDS;
}
}
// Channel info. Attributes of a channel.
struct ieee80211_channel {
enum nl80211_band band; // This value can be obtained from convert_wlan_band_to_nl80211_band(
// iwl_mvm_get_channel_band(ch_num)).
uint32_t center_freq; // unit: MHz.
uint16_t ch_num; // channel number (starts from 1). TODO(fxbug.dev/119415): remove this.
uint16_t hw_value; // channel number (starts from 1). From wlan_channel_t.primary.
uint32_t flags;
int max_power;
};
// This is similar with 'channel_bandwidth_t'.
enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT,
NL80211_CHAN_WIDTH_20,
NL80211_CHAN_WIDTH_40,
NL80211_CHAN_WIDTH_80,
NL80211_CHAN_WIDTH_80P80,
NL80211_CHAN_WIDTH_160,
NL80211_CHAN_WIDTH_5,
NL80211_CHAN_WIDTH_10,
// Below value should be used in the test case.
NL80211_CHAN_WIDTH_40_BELOW,
};
static inline channel_bandwidth_t convert_nl80211_chan_width_to_channel_bandwidth(
enum nl80211_chan_width width) {
switch (width) {
case NL80211_CHAN_WIDTH_20:
return CHANNEL_BANDWIDTH_CBW20;
case NL80211_CHAN_WIDTH_40:
return CHANNEL_BANDWIDTH_CBW40;
case NL80211_CHAN_WIDTH_40_BELOW:
return CHANNEL_BANDWIDTH_CBW40BELOW;
case NL80211_CHAN_WIDTH_80:
return CHANNEL_BANDWIDTH_CBW80;
case NL80211_CHAN_WIDTH_160:
return CHANNEL_BANDWIDTH_CBW160;
case NL80211_CHAN_WIDTH_80P80:
return CHANNEL_BANDWIDTH_CBW80P80;
default:
break;
}
return CHANNEL_BANDWIDTH_CBW20;
}
static inline enum nl80211_chan_width convert_channel_bandwidth_to_nl80211_chan_width(
channel_bandwidth_t cbw) {
switch (cbw) {
case CHANNEL_BANDWIDTH_CBW20:
return NL80211_CHAN_WIDTH_20;
case CHANNEL_BANDWIDTH_CBW40:
return NL80211_CHAN_WIDTH_40;
case CHANNEL_BANDWIDTH_CBW40BELOW:
return NL80211_CHAN_WIDTH_40_BELOW;
case CHANNEL_BANDWIDTH_CBW80:
return NL80211_CHAN_WIDTH_80;
case CHANNEL_BANDWIDTH_CBW160:
return NL80211_CHAN_WIDTH_160;
case CHANNEL_BANDWIDTH_CBW80P80:
return NL80211_CHAN_WIDTH_80P80;
default:
break;
}
return NL80211_CHAN_WIDTH_20_NOHT;
}
// This can be converted from the `wlan_channel_t` structure.
struct cfg80211_chan_def {
struct ieee80211_channel* chan; // .hw_value = wlan_channel_t.primary
enum nl80211_chan_width width; // = wlan_channel_t.cbw
};
struct ieee80211_mcs_info {
uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN];
__le16 rx_highest_le;
uint8_t tx_params;
uint8_t reserved[3];
} __packed;
struct ieee80211_sta_ht_cap {
uint16_t cap; /* use IEEE80211_HT_CAP_ */
bool ht_supported;
uint8_t ampdu_factor;
uint8_t ampdu_density;
struct ieee80211_mcs_info mcs;
};
struct ieee80211_supported_band {
wlan_band_t band;
struct ieee80211_channel* channels;
size_t n_channels;
uint16_t* bitrates;
size_t n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
};
struct ieee80211_tx_queue_params {
uint16_t txop;
uint16_t cw_min;
uint16_t cw_max;
uint8_t aifs;
};
struct ieee80211_tx_rate {
char dummy;
};
struct ieee80211_txq;
struct ieee80211_sta {
void* drv_priv;
struct ieee80211_txq* txq[fuchsia_wlan_ieee80211_TIDS_MAX + 1];
};
struct ieee80211_txq {
void* drv_priv;
};
struct cfg80211_ssid {
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
};
enum nl80211_iftype {
NL80211_IFTYPE_UNSPECIFIED,
NL80211_IFTYPE_STATION,
NL80211_IFTYPE_P2P_DEVICE,
};
struct ieee80211_vif {
enum nl80211_iftype type;
void* drv_priv;
};
enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1 << 0,
NL80211_SCAN_FLAG_FLUSH = 1 << 1,
NL80211_SCAN_FLAG_AP = 1 << 2,
NL80211_SCAN_FLAG_RANDOM_ADDR = 1 << 3,
NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 1 << 4,
NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 1 << 5,
NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 1 << 6,
NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 1 << 7,
NL80211_SCAN_FLAG_LOW_SPAN = 1 << 8,
NL80211_SCAN_FLAG_LOW_POWER = 1 << 9,
NL80211_SCAN_FLAG_HIGH_ACCURACY = 1 << 10,
NL80211_SCAN_FLAG_RANDOM_SN = 1 << 11,
NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1 << 12,
NL80211_SCAN_FLAG_FREQ_KHZ = 1 << 13,
NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1 << 14,
};
/**
* struct ieee80211_key_conf - HW key configuration data
* @tx_pn - TX packet number, in host byte order
* @rx_seq - RX sequence number, in host byte order
*/
struct ieee80211_key_conf {
atomic64_t tx_pn;
uint64_t rx_seq;
uint32_t cipher;
uint8_t hw_key_idx;
uint8_t keyidx;
uint8_t key_type;
size_t keylen;
uint8_t key[0];
};
struct ieee80211_tx_info {
struct {
struct ieee80211_key_conf* hw_key;
} control;
};
// Struct for transferring an IEEE 802.11 MAC-framed packet around the driver.
struct ieee80211_mac_packet {
// The common portion of the MAC header.
const struct ieee80211_frame_header* common_header;
// The size of the entire MAC header (starting at common_header), including variable fields.
size_t header_size;
// Statically allocated headroom space between the MAC header and frame body, for adding
// additional headers to the packet.
uint8_t headroom[IEEE80211_MAC_PACKET_HEADROOM_SIZE];
// Size of the headroom used.
size_t headroom_used_size;
// MAC frame body.
const uint8_t* body;
// MAC frame body size.
size_t body_size;
// Control information for this packet.
struct ieee80211_tx_info info;
};
// Flags for the ieee80211_rx_status.flag
enum ieee80211_rx_status_flags {
RX_FLAG_DECRYPTED = 0x1,
RX_FLAG_PN_VALIDATED = 0x2,
RX_FLAG_ALLOW_SAME_PN = 0x4,
};
struct ieee80211_rx_status {
// RX flags, as in Linux.
uint64_t flag;
// The encryption IV, copied here since the encryption header is removed for Fuchsia.
uint8_t extiv[8];
// RX info struct to pass to wlanstack.
struct wlan_rx_info rx_info;
};
size_t ieee80211_get_header_len(const struct ieee80211_frame_header* fh);
struct ieee80211_hw* ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops* ops);
bool ieee80211_is_valid_chan(uint8_t primary);
uint16_t ieee80211_get_center_freq(uint8_t channel_num);
bool ieee80211_has_protected(const struct ieee80211_frame_header* fh);
bool ieee80211_is_data(const struct ieee80211_frame_header* fh);
bool ieee80211_is_data_present(const struct ieee80211_frame_header* fh);
bool ieee80211_is_data_qos(const struct ieee80211_frame_header* fh);
uint8_t ieee80211_get_tid(const struct ieee80211_frame_header* fh);
bool ieee80211_is_back_req(const struct ieee80211_frame_header* fh);
static inline uint16_t ieee80211_get_qos_ctl(const struct ieee80211_frame_header* fh) {
uint8_t* p = (uint8_t*)fh;
size_t offset = ieee80211_get_qos_ctrl_offset(fh);
return *((uint16_t*)(p + offset));
}
#if defined(__cplusplus)
} // extern "C"
#endif // defined(__cplusplus)
#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_IEEE80211_H_