| /* |
| * Copyright 2018 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. |
| */ |
| |
| #ifndef GARNET_DRIVERS_WLAN_THIRD_PARTY_ATHEROS_ATH10K_IEEE80211_H_ |
| #define GARNET_DRIVERS_WLAN_THIRD_PARTY_ATHEROS_ATH10K_IEEE80211_H_ |
| |
| #include <stdint.h> |
| |
| #include <zircon/assert.h> |
| |
| #include "hw.h" |
| |
| // clang-format off |
| // IEEE Std 802.11-2016, 9.2.3 |
| struct ieee80211_frame_header { |
| uint16_t frame_ctrl; |
| uint16_t duration; |
| uint8_t addr1[ETH_ALEN]; |
| uint8_t addr2[ETH_ALEN]; |
| uint8_t addr3[ETH_ALEN]; |
| uint16_t seq_ctrl; |
| uint8_t addr4[0]; |
| } __PACKED; |
| |
| // IEEE Std 802.11-2016, 9.3.3.7 |
| struct ieee80211_assoc_resp { |
| uint16_t capabilities; |
| uint16_t status; |
| uint16_t assoc_id; |
| uint8_t info[0]; |
| } __PACKED; |
| |
| // IEEE Std 802.11-2016, 9.4.2.57 |
| struct ieee80211_ht_info { |
| uint8_t primary_channel; |
| uint8_t ht_operation_info[5]; |
| uint8_t rx_mcs[10]; |
| } __PACKED; |
| |
| // IEEE Std 802.11-2016, 9.2.4.1.3 |
| enum ieee80211_frame_type { |
| IEEE80211_FRAME_TYPE_MGMT = 0x0, |
| IEEE80211_FRAME_TYPE_CTRL = 0x4, |
| IEEE80211_FRAME_TYPE_DATA = 0x8, |
| IEEE80211_FRAME_TYPE_EXT = 0xc, |
| }; |
| |
| // IEEE Std 802.11-2016, 9.2.4.1.3 |
| enum ieee80211_frame_subtype { |
| /* MGMT */ |
| IEEE80211_FRAME_SUBTYPE_ASSOC_REQ = 0x00, |
| IEEE80211_FRAME_SUBTYPE_ASSOC_RESP = 0x10, |
| IEEE80211_FRAME_SUBTYPE_BEACON = 0x80, |
| IEEE80211_FRAME_SUBTYPE_DISASSOC = 0xa0, |
| IEEE80211_FRAME_SUBTYPE_DEAUTH = 0xc0, |
| IEEE80211_FRAME_SUBTYPE_ACTION = 0xd0, |
| |
| /* DATA */ |
| IEEE80211_FRAME_SUBTYPE_PROBE_RESP = 0x50, |
| IEEE80211_FRAME_SUBTYPE_QOS = 0x80, |
| IEEE80211_FRAME_SUBTYPE_QOS_NULL = 0xc0, |
| |
| /* CONTROL */ |
| IEEE80211_FRAME_SUBTYPE_CTS = 0xc0, |
| IEEE80211_FRAME_SUBTYPE_ACK = 0xd0, |
| }; |
| |
| enum nl80211_band { |
| NL80211_BAND_2GHZ, |
| NL80211_BAND_5GHZ, |
| NL80211_BAND_60GHZ, |
| }; |
| |
| // IEEE Std 802.11-2016, 9.2.4.1.1 |
| #define IEEE80211_FRAME_TYPE_MASK 0x000c |
| #define IEEE80211_FRAME_SUBTYPE_MASK 0x00f0 |
| #define IEEE80211_FRAME_CTRL_TO_DS_MASK 0x0100 |
| #define IEEE80211_FRAME_CTRL_FROM_DS_MASK 0x0200 |
| #define IEEE80211_FRAME_CTRL_MORE_FRAGMENTS_MASK 0x0400 |
| #define IEEE80211_FRAME_PROTECTED_MASK 0x4000 |
| #define IEEE80211_FRAME_CTRL_HTC_ORDER_MASK 0x8000 |
| |
| // IEEE Std 802.11-2016, 9.2.4.5.1 |
| #define IEEE80211_QOS_CTRL_A_MSDU_PRESENT 0x0080 |
| |
| static inline enum ieee80211_frame_type |
| ieee80211_get_frame_type(const struct ieee80211_frame_header* fh) { |
| return fh->frame_ctrl & IEEE80211_FRAME_TYPE_MASK; |
| } |
| |
| static inline enum ieee80211_frame_subtype |
| ieee80211_get_frame_subtype(const struct ieee80211_frame_header* fh) { |
| return fh->frame_ctrl & IEEE80211_FRAME_SUBTYPE_MASK; |
| } |
| |
| static inline bool ieee80211_pkt_is_protected(const struct ieee80211_frame_header* fh) { |
| return fh->frame_ctrl & IEEE80211_FRAME_PROTECTED_MASK; |
| } |
| |
| static inline uint8_t* ieee80211_get_bssid(struct ieee80211_frame_header* fh) { |
| ZX_ASSERT(ieee80211_get_frame_type(fh) == IEEE80211_FRAME_TYPE_MGMT); |
| return fh->addr3; |
| } |
| |
| static bool ieee80211_has_addr4(const struct ieee80211_frame_header* hdr) { |
| uint16_t mask = IEEE80211_FRAME_CTRL_TO_DS_MASK | IEEE80211_FRAME_CTRL_FROM_DS_MASK; |
| return (hdr->frame_ctrl & mask) == mask; |
| } |
| |
| static inline size_t ieee80211_is_qos_data(struct ieee80211_frame_header* fh) { |
| return ieee80211_get_frame_type(fh) == IEEE80211_FRAME_TYPE_DATA |
| && (ieee80211_get_frame_subtype(fh) & IEEE80211_FRAME_SUBTYPE_QOS); |
| } |
| |
| static inline size_t ieee80211_get_qos_ctrl_offset(const struct ieee80211_frame_header* hdr) { |
| return sizeof(struct ieee80211_frame_header) + (ieee80211_has_addr4(hdr) ? ETH_ALEN : 0); |
| } |
| |
| static inline size_t ieee80211_hdrlen(struct ieee80211_frame_header* fh) { |
| switch (ieee80211_get_frame_type(fh)) { |
| case IEEE80211_FRAME_TYPE_MGMT: |
| case IEEE80211_FRAME_TYPE_DATA: |
| return sizeof(struct ieee80211_frame_header) |
| + (ieee80211_has_addr4(fh) ? ETH_ALEN : 0) |
| + (ieee80211_is_qos_data(fh) ? 2 : 0) |
| + ((fh->frame_ctrl & IEEE80211_FRAME_CTRL_HTC_ORDER_MASK) ? 4 : 0); |
| case IEEE80211_FRAME_TYPE_CTRL: |
| // See IEEE Std. 802.11-2016, 9.3.1 |
| switch (ieee80211_get_frame_subtype(fh)) { |
| case IEEE80211_FRAME_SUBTYPE_CTS: |
| case IEEE80211_FRAME_SUBTYPE_ACK: |
| return 10; |
| default: |
| return 16; |
| } |
| default: |
| return sizeof(struct ieee80211_frame_header); |
| } |
| } |
| |
| static inline uint8_t* ieee80211_get_dest_addr(struct ieee80211_frame_header* fh) { |
| if (fh->frame_ctrl & IEEE80211_FRAME_CTRL_TO_DS_MASK) { |
| return fh->addr3; |
| } else { |
| return fh->addr1; |
| } |
| } |
| |
| static inline uint8_t* ieee80211_get_src_addr(struct ieee80211_frame_header* fh) { |
| uint16_t mask = IEEE80211_FRAME_CTRL_TO_DS_MASK | IEEE80211_FRAME_CTRL_FROM_DS_MASK; |
| switch (fh->frame_ctrl & mask) { |
| case IEEE80211_FRAME_CTRL_TO_DS_MASK | IEEE80211_FRAME_CTRL_FROM_DS_MASK: |
| return fh->addr4; |
| case IEEE80211_FRAME_CTRL_FROM_DS_MASK: |
| return fh->addr3; |
| default: |
| return fh->addr2; |
| } |
| } |
| |
| #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 |
| |
| // IEEE Std 802.11-2016, 9.4.2.1, Table 9-77 |
| enum ieee80211_assoc_tags { |
| IEEE80211_ASSOC_TAG_RATES = 1, |
| IEEE80211_ASSOC_TAG_HT_CAPS = 45, |
| IEEE80211_ASSOC_TAG_EXTENDED_RATES = 50, |
| IEEE80211_ASSOC_TAG_HT_INFO = 61, |
| }; |
| |
| // IEEE Std 802.11-2016, 9.4.2.56.2, Figure 9-332 |
| enum ieee80211_ht_caps { |
| IEEE80211_HT_CAPS_LDPC = 0x0001, |
| IEEE80211_HT_CAPS_CHAN_WIDTH = 0x0002, |
| IEEE80211_HT_CAPS_SMPS = 0x000c, |
| IEEE80211_HT_CAPS_SMPS_STATIC = 0x0000, |
| IEEE80211_HT_CAPS_SMPS_DYNAMIC = 0x0004, |
| IEEE80211_HT_CAPS_SMPS_DISABLED = 0x000c, |
| IEEE80211_HT_CAPS_SMPS_SHIFT = 2, |
| IEEE80211_HT_CAPS_GF = 0x0010, |
| IEEE80211_HT_CAPS_SGI_20 = 0x0020, |
| IEEE80211_HT_CAPS_SGI_40 = 0x0040, |
| IEEE80211_HT_CAPS_TX_STBC = 0x0080, |
| IEEE80211_HT_CAPS_RX_STBC = 0x0300, |
| IEEE80211_HT_CAPS_RX_STBC_SHIFT = 8, |
| IEEE80211_HT_CAPS_DELAYED_BLOCK_ACK = 0x0400, |
| IEEE80211_HT_CAPS_MAX_AMSDU_LEN = 0x0800, |
| IEEE80211_HT_CAPS_DSSS_CCK_40 = 0x1000, |
| /* RESERVED - bit 13 */ |
| IEEE80211_HT_CAPS_40_INTOLERANT = 0x4000, |
| IEEE80211_HT_CAPS_L_SIG_TXOP_PROT = 0x8000 |
| }; |
| |
| #define IEEE80211_HT_MCS_MASK_LEN 10 |
| |
| enum ieee80211_ampdu_params { |
| IEEE80211_AMPDU_RX_LEN_MASK = 0x03, |
| IEEE80211_AMPDU_RX_LEN_SHIFT = 0, |
| IEEE80211_AMPDU_DENSITY_MASK = 0x1c, |
| IEEE80211_AMPDU_DENSITY_SHIFT = 2 |
| }; |
| |
| // IEEE Std. 802.11-2016 9.4.2.158.2 |
| enum ieee80211_vht_caps { |
| IEEE80211_VHT_CAPS_MAX_MPDU_LEN = 0x3, |
| IEEE80211_VHT_CAPS_MAX_MPDU_LEN_SHIFT = 0, |
| IEEE80211_VHT_CAPS_SUPP_CHAN_WIDTH = 0xc, |
| IEEE80211_VHT_CAPS_SUPP_CHAN_WIDTH_SHIFT = 2, |
| IEEE80211_VHT_CAPS_RX_LDPC = 0x10, |
| IEEE80211_VHT_CAPS_RX_LDPC_SHIFT = 4, |
| IEEE80211_VHT_CAPS_SGI_80 = 0x20, |
| IEEE80211_VHT_CAPS_SGI_80_SHIFT = 5, |
| IEEE80211_VHT_CAPS_SGI_160 = 0x40, |
| IEEE80211_VHT_CAPS_SGI_160_SHIFT = 6, |
| IEEE80211_VHT_CAPS_TX_STBC = 0x80, |
| IEEE80211_VHT_CAPS_TX_STBC_SHIFT = 7, |
| IEEE80211_VHT_CAPS_RX_STBC = 0x700, |
| IEEE80211_VHT_CAPS_RX_STBC_SHIFT = 8, |
| IEEE80211_VHT_CAPS_SU_BEAMFORMER = 0x800, |
| IEEE80211_VHT_CAPS_SU_BEAMFORMER_SHIFT = 11, |
| IEEE80211_VHT_CAPS_SU_BEAMFORMEE = 0x1000, |
| IEEE80211_VHT_CAPS_SU_BEAMFORMEE_SHIFT = 12, |
| IEEE80211_VHT_CAPS_BEAMFORMEE_STS = 0xe000, |
| IEEE80211_VHT_CAPS_BEAMFORMEE_STS_SHIFT = 13, |
| IEEE80211_VHT_CAPS_SOUND_DIM = 0x70000, |
| IEEE80211_VHT_CAPS_SOUND_DIM_SHIFT = 16, |
| IEEE80211_VHT_CAPS_MU_BEAMFORMER = 0x80000, |
| IEEE80211_VHT_CAPS_MU_BEAMFORMER_SHIFT = 19, |
| IEEE80211_VHT_CAPS_MU_BEAMFORMEE = 0x100000, |
| IEEE80211_VHT_CAPS_MU_BEAMFORMEE_SHIFT = 20, |
| IEEE80211_VHT_CAPS_TXOP_PS = 0x200000, |
| IEEE80211_VHT_CAPS_TXOP_PS_SHIFT = 21, |
| IEEE80211_VHT_CAPS_HTC_VHT = 0x400000, |
| IEEE80211_VHT_CAPS_HTC_VHT_SHIFT = 22, |
| IEEE80211_VHT_CAPS_MAX_AMPDU_LEN = 0x3800000, |
| IEEE80211_VHT_CAPS_MAX_AMPDU_LEN_SHIFT = 23, |
| IEEE80211_VHT_CAPS_VHT_LINK_ADAPT = 0xc000000, |
| IEEE80211_VHT_CAPS_VHT_LINK_ADAPT_SHIFT = 26, |
| IEEE80211_VHT_CAPS_RX_ANT_CONSIST = 0x10000000, |
| IEEE80211_VHT_CAPS_RX_ANT_CONSIST_SHIFT = 28, |
| IEEE80211_VHT_CAPS_TX_ANT_CONSIST = 0x20000000, |
| IEEE80211_VHT_CAPS_TX_ANT_CONSIST_SHIFT = 29, |
| IEEE80211_VHT_CAPS_EXT_NSS_BW = 0xc0000000, |
| IEEE80211_VHT_CAPS_EXT_NSS_BW_SHIFT = 30 |
| }; |
| |
| // IEEE Std. 802.11-2016 9.4.2.158.3 |
| enum ieee80211_supported_vht_mcs_nss { |
| IEEE80211_VHT_MCS_NSS_RX_MCS_MAP = 0xffff, |
| IEEE80211_VHT_MCS_NSS_RX_MCS_MAP_SHIFT = 0, |
| IEEE80211_VHT_MCS_NSS_RX_MAX_LGI_RATE = 0x1fff0000, |
| IEEE80211_VHT_MCS_NSS_RX_MAX_LGI_RATE_SHIFT = 16, |
| IEEE80211_VHT_MCS_NSS_MAX_NSTS = 0xe0000000, |
| IEEE80211_VHT_MCS_NSS_MAX_NSTS_SHIFT = 29, |
| IEEE80211_VHT_MCS_NSS_TX_MCS_MAP = 0xffff00000000, |
| IEEE80211_VHT_MCS_NSS_TX_MCS_MAP_SHIFT = 32, |
| IEEE80211_VHT_MCS_NSS_TX_MAX_LGI_RATE = 0x1fff000000000000, |
| IEEE80211_VHT_MCS_NSS_TX_MAX_LGI_RATE_SHIFT = 48, |
| IEEE80211_VHT_MCS_NSS_EXT_NSS_BW_CAP = 0x2000000000000000, |
| IEEE80211_VHT_MCS_NSS_EXT_NSS_BW_CAP_SHIFT = 61, |
| }; |
| |
| // Max VHT-MCS SS encodings (IEEE Std. 802.11-2016 9.4.2.158.3) |
| #define IEEE80211_VHT_MCS_0_7 0 |
| #define IEEE80211_VHT_MCS_0_8 1 |
| #define IEEE80211_VHT_MCS_0_9 2 |
| #define IEEE80211_VHT_MCS_NONE 3 |
| |
| #define IEEE80211_CCMP_MIC_LEN 8 |
| #define IEEE80211_QOS_CTL_LEN 2 |
| |
| #define IEEE80211_MSDU_SIZE_MAX 2304 |
| |
| // IEEE Std 802.11-2016, 9.2.4.8 |
| #define IEEE80211_FCS_LEN 4 |
| |
| // IEEE Std 802.11-2016, 12.3.2.2 |
| #define IEEE80211_WEP_IV_LEN 4 |
| #define IEEE80211_WEP_ICV_LEN 4 |
| |
| // IEEE Std 802.11-2016, 12.5.2.2 |
| #define IEEE80211_TKIP_IV_LEN 8 |
| #define IEEE80211_TKIP_ICV_LEN 4 |
| |
| // IEEE Std 802.11-2016, 12.5.3.2 |
| #define IEEE80211_CCMP_HDR_LEN 8 |
| #define IEEE80211_CCMP_128_MIC_LEN 8 |
| |
| // IEEE Std 802.11-2016, 9.4.2.2 |
| #define IEEE80211_SSID_LEN_MAX 32 |
| |
| // IEEE Std 802.11-2016, 9.4.2.25.2, Table 9-131 |
| enum ieee80211_cipher_suite { |
| IEEE80211_CIPHER_SUITE_GROUP = 0, |
| IEEE80211_CIPHER_SUITE_WEP_40 = 1, |
| IEEE80211_CIPHER_SUITE_TKIP = 2, |
| IEEE80211_CIPHER_SUITE_CCMP_128 = 4, |
| IEEE80211_CIPHER_SUITE_WEP_104 = 5, |
| IEEE80211_CIPHER_SUITE_CMAC_128 = 6, |
| IEEE80211_CIPHER_SUITE_GCMP_128 = 8, |
| IEEE80211_CIPHER_SUITE_GCMP_256 = 9, |
| IEEE80211_CIPHER_SUITE_CCMP_256 = 10, |
| IEEE80211_CIPHER_SUITE_GMAC_128 = 11, |
| IEEE80211_CIPHER_SUITE_GMAC_256 = 12, |
| IEEE80211_CIPHER_SUITE_CMAC_256 = 13, |
| IEEE80211_CIPHER_SUITE_NONE = 255, // Not in the spec, a special value for driver to delete |
| // a key. |
| }; |
| |
| static inline const char* ieee80211_cipher_str(uint8_t* oui, uint8_t cipher_type) { |
| if (oui[0] != 0 || oui[1] != 0x0f || oui[2] != 0xac) { |
| return "vendor-specific OUI\n"; |
| } |
| switch (cipher_type) { |
| case IEEE80211_CIPHER_SUITE_GROUP: |
| return "group"; |
| case IEEE80211_CIPHER_SUITE_WEP_40: |
| return "WEP40"; |
| case IEEE80211_CIPHER_SUITE_TKIP: |
| return "TKIP"; |
| case IEEE80211_CIPHER_SUITE_CCMP_128: |
| return "CCMP128"; |
| case IEEE80211_CIPHER_SUITE_WEP_104: |
| return "WEP104"; |
| case IEEE80211_CIPHER_SUITE_CMAC_128: |
| return "CMAC_128"; |
| case IEEE80211_CIPHER_SUITE_GCMP_128: |
| return "GCMP128"; |
| case IEEE80211_CIPHER_SUITE_GCMP_256: |
| return "GCMP256"; |
| case IEEE80211_CIPHER_SUITE_CCMP_256: |
| return "CCMP256"; |
| case IEEE80211_CIPHER_SUITE_GMAC_128: |
| return "GMAC128"; |
| case IEEE80211_CIPHER_SUITE_GMAC_256: |
| return "GMAC256"; |
| case IEEE80211_CIPHER_SUITE_CMAC_256: |
| return "CMAC256"; |
| default: |
| return "reserved CID value\n"; |
| } |
| } |
| // clang-format on |
| |
| #endif // GARNET_DRIVERS_WLAN_THIRD_PARTY_ATHEROS_ATH10K_IEEE80211_H_ |