2108 lines
75 KiB
C
2108 lines
75 KiB
C
/*
|
|
* mac80211 <-> driver interface
|
|
*
|
|
* Copyright 2002-2005, Devicescape Software, Inc.
|
|
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
|
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#ifndef ATBM_MAC80211_H
|
|
#define ATBM_MAC80211_H
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/if_ether.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/device.h>
|
|
#include <linux/ieee80211.h>
|
|
#include <net/cfg80211.h>
|
|
#include <asm/unaligned.h>
|
|
#include <linux/hash.h>
|
|
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
|
|
#define IEEE80211_BAND_2GHZ NL80211_BAND_2GHZ
|
|
#define IEEE80211_BAND_5GHZ NL80211_BAND_5GHZ
|
|
#define IEEE80211_NUM_BANDS (NL80211_BAND_5GHZ+1)
|
|
#define ieee80211_band nl80211_band
|
|
#define atbm_notify_scan_done(__local,__scan_request,__abort) \
|
|
do { \
|
|
__local->scan_info.aborted = __abort; \
|
|
cfg80211_scan_done(__scan_request,&__local->scan_info); \
|
|
}while(0)
|
|
#else
|
|
struct cfg80211_scan_info{
|
|
bool aborted;
|
|
};
|
|
#define atbm_notify_scan_done(__local,__scan_request,__abort) \
|
|
do { \
|
|
BUG_ON(__local==NULL); \
|
|
cfg80211_scan_done(__scan_request,__abort); \
|
|
}while(0)
|
|
#endif
|
|
|
|
#ifdef IPV6_FILTERING
|
|
#include <linux/in6.h>
|
|
#endif /*IPV6_FILTERING*/
|
|
|
|
#ifndef IEEE80211_QOS_CTL_EOSP
|
|
#define IEEE80211_QOS_CTL_EOSP 0x0010
|
|
#endif
|
|
|
|
#ifndef IEEE80211_BAR_CTRL_MULTI_TID
|
|
#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002
|
|
#endif
|
|
#ifndef IEEE80211_BAR_CTRL_TID_INFO_MASK
|
|
#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000
|
|
#endif
|
|
|
|
#ifndef IEEE80211_BAR_CTRL_TID_INFO_SHIFT
|
|
#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12
|
|
#endif
|
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
|
|
#ifndef IEEE80211_RADIOTAP_F_TX_NOACK
|
|
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
|
|
#endif
|
|
#endif
|
|
#ifndef IEEE80211_QOS_CTL_ACK_POLICY_NOACK
|
|
#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020
|
|
#endif
|
|
|
|
#ifndef IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT
|
|
#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100
|
|
#endif
|
|
|
|
#ifndef ERP_INFO_BYTE_OFFSET
|
|
#define ERP_INFO_BYTE_OFFSET 2
|
|
#endif
|
|
|
|
static inline unsigned atbm_compare_ether_addr(const u8 *addr1, const u8 *addr2)
|
|
{
|
|
const u16 *a = (const u16 *) addr1;
|
|
const u16 *b = (const u16 *) addr2;
|
|
|
|
BUILD_BUG_ON(ETH_ALEN != 6);
|
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
|
|
}
|
|
/* Information Element IDs */
|
|
enum atbm_ieee80211_eid {
|
|
ATBM_WLAN_EID_SSID = 0,
|
|
ATBM_WLAN_EID_SUPP_RATES = 1,
|
|
ATBM_WLAN_EID_FH_PARAMS = 2,
|
|
ATBM_WLAN_EID_DS_PARAMS = 3,
|
|
ATBM_WLAN_EID_CF_PARAMS = 4,
|
|
ATBM_WLAN_EID_TIM = 5,
|
|
ATBM_WLAN_EID_IBSS_PARAMS = 6,
|
|
ATBM_WLAN_EID_CHALLENGE = 16,
|
|
|
|
ATBM_WLAN_EID_COUNTRY = 7,
|
|
ATBM_WLAN_EID_HP_PARAMS = 8,
|
|
ATBM_WLAN_EID_HP_TABLE = 9,
|
|
ATBM_WLAN_EID_REQUEST = 10,
|
|
|
|
ATBM_WLAN_EID_QBSS_LOAD = 11,
|
|
ATBM_WLAN_EID_EDCA_PARAM_SET = 12,
|
|
ATBM_WLAN_EID_TSPEC = 13,
|
|
ATBM_WLAN_EID_TCLAS = 14,
|
|
ATBM_WLAN_EID_SCHEDULE = 15,
|
|
ATBM_WLAN_EID_TS_DELAY = 43,
|
|
ATBM_WLAN_EID_TCLAS_PROCESSING = 44,
|
|
ATBM_WLAN_EID_QOS_CAPA = 46,
|
|
/* 802.11z */
|
|
ATBM_WLAN_EID_LINK_ID = 101,
|
|
/* 802.11s */
|
|
ATBM_WLAN_EID_MESH_CONFIG = 113,
|
|
ATBM_WLAN_EID_MESH_ID = 114,
|
|
ATBM_WLAN_EID_LINK_METRIC_REPORT = 115,
|
|
ATBM_WLAN_EID_CONGESTION_NOTIFICATION = 116,
|
|
ATBM_WLAN_EID_PEER_MGMT = 117,
|
|
ATBM_WLAN_EID_CHAN_SWITCH_PARAM = 118,
|
|
ATBM_WLAN_EID_MESH_AWAKE_WINDOW = 119,
|
|
ATBM_WLAN_EID_BEACON_TIMING = 120,
|
|
ATBM_WLAN_EID_MCCAOP_SETUP_REQ = 121,
|
|
ATBM_WLAN_EID_MCCAOP_SETUP_RESP = 122,
|
|
ATBM_WLAN_EID_MCCAOP_ADVERT = 123,
|
|
ATBM_WLAN_EID_MCCAOP_TEARDOWN = 124,
|
|
ATBM_WLAN_EID_GANN = 125,
|
|
ATBM_WLAN_EID_RANN = 126,
|
|
ATBM_WLAN_EID_PREQ = 130,
|
|
ATBM_WLAN_EID_PREP = 131,
|
|
ATBM_WLAN_EID_PERR = 132,
|
|
ATBM_WLAN_EID_PXU = 137,
|
|
ATBM_WLAN_EID_PXUC = 138,
|
|
ATBM_WLAN_EID_AUTH_MESH_PEER_EXCH = 139,
|
|
ATBM_WLAN_EID_MIC = 140,
|
|
|
|
ATBM_WLAN_EID_PWR_CONSTRAINT = 32,
|
|
ATBM_WLAN_EID_PWR_CAPABILITY = 33,
|
|
ATBM_WLAN_EID_TPC_REQUEST = 34,
|
|
ATBM_WLAN_EID_TPC_REPORT = 35,
|
|
ATBM_WLAN_EID_SUPPORTED_CHANNELS = 36,
|
|
ATBM_WLAN_EID_CHANNEL_SWITCH = 37,
|
|
ATBM_WLAN_EID_MEASURE_REQUEST = 38,
|
|
ATBM_WLAN_EID_MEASURE_REPORT = 39,
|
|
ATBM_WLAN_EID_QUIET = 40,
|
|
ATBM_WLAN_EID_IBSS_DFS = 41,
|
|
|
|
ATBM_WLAN_EID_ERP_INFO = 42,
|
|
ATBM_WLAN_EID_EXT_SUPP_RATES = 50,
|
|
|
|
ATBM_WLAN_EID_HT_CAPABILITY = 45,
|
|
ATBM_WLAN_EID_HT_INFORMATION = 61,
|
|
|
|
ATBM_WLAN_EID_RSN = 48,
|
|
ATBM_WLAN_EID_MMIE = 76,
|
|
ATBM_WLAN_EID_WPA = 221,
|
|
ATBM_WLAN_EID_GENERIC = 221,
|
|
ATBM_WLAN_EID_VENDOR_SPECIFIC = 221,
|
|
ATBM_WLAN_EID_QOS_PARAMETER = 222,
|
|
|
|
ATBM_WLAN_EID_AP_CHAN_REPORT = 51,
|
|
ATBM_WLAN_EID_NEIGHBOR_REPORT = 52,
|
|
ATBM_WLAN_EID_RCPI = 53,
|
|
ATBM_WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
|
|
ATBM_WLAN_EID_ANTENNA_INFO = 64,
|
|
ATBM_WLAN_EID_RSNI = 65,
|
|
ATBM_WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
|
|
ATBM_WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
|
|
ATBM_WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
|
|
ATBM_WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
|
ATBM_WLAN_EID_MULTIPLE_BSSID = 71,
|
|
ATBM_WLAN_EID_BSS_COEX_2040 = 72,
|
|
ATBM_WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
|
ATBM_WLAN_EID_EXT_CAPABILITY = 127,
|
|
|
|
ATBM_WLAN_EID_MOBILITY_DOMAIN = 54,
|
|
ATBM_WLAN_EID_FAST_BSS_TRANSITION = 55,
|
|
ATBM_WLAN_EID_TIMEOUT_INTERVAL = 56,
|
|
ATBM_WLAN_EID_RIC_DATA = 57,
|
|
ATBM_WLAN_EID_RIC_DESCRIPTOR = 75,
|
|
|
|
ATBM_WLAN_EID_DSE_REGISTERED_LOCATION = 58,
|
|
ATBM_WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
|
|
ATBM_WLAN_EID_EXT_CHANSWITCH_ANN = 60,
|
|
ATBM_WLAN_EID_SECONDARY_CH_OFFSET = 62,
|
|
ATBM_WLAN_EID_PRIVATE = 233,
|
|
};
|
|
|
|
struct atbm_wpa_ie_data {
|
|
int proto;
|
|
int pairwise_cipher;
|
|
int group_cipher;
|
|
int key_mgmt;
|
|
int wpa_capabilities;
|
|
int rsn_capabilities;
|
|
size_t num_pmkid;
|
|
const u8 *pmkid;
|
|
int mgmt_group_cipher;
|
|
};
|
|
#define ATBM_WLAN_CAPABILITY_ESS BIT(0)
|
|
#define ATBM_WLAN_CAPABILITY_IBSS BIT(1)
|
|
#define ATBM_WLAN_CAPABILITY_CF_POLLABLE BIT(2)
|
|
#define ATBM_WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
|
|
#define ATBM_WLAN_CAPABILITY_PRIVACY BIT(4)
|
|
#define ATBM_WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
|
|
#define ATBM_WLAN_CAPABILITY_PBCC BIT(6)
|
|
#define ATBM_WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
|
#define ATBM_WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
|
#define ATBM_WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
|
#define ATBM_WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
|
|
|
/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */
|
|
#define ATBM_WPA_CAPABILITY_PREAUTH BIT(0)
|
|
#define ATBM_WPA_CAPABILITY_NO_PAIRWISE BIT(1)
|
|
/* B2-B3: PTKSA Replay Counter */
|
|
/* B4-B5: GTKSA Replay Counter */
|
|
#define ATBM_WPA_CAPABILITY_MFPR BIT(6)
|
|
#define ATBM_WPA_CAPABILITY_MFPC BIT(7)
|
|
/* B8: Reserved */
|
|
#define ATBM_WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
|
|
#define ATBM_WPA_CAPABILITY_SPP_A_MSDU_CAPABLE BIT(10)
|
|
#define ATBM_WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11)
|
|
#define ATBM_WPA_CAPABILITY_PBAC BIT(12)
|
|
#define ATBM_WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13)
|
|
|
|
#define ATBM_WPA_PROTO_WPA BIT(0)
|
|
#define ATBM_WPA_PROTO_RSN BIT(1)
|
|
#define ATBM_WPA_PROTO_WAPI BIT(2)
|
|
|
|
#define ATBM_WPA_CIPHER_NONE BIT(0)
|
|
#define ATBM_WPA_CIPHER_WEP40 BIT(1)
|
|
#define ATBM_WPA_CIPHER_WEP104 BIT(2)
|
|
#define ATBM_WPA_CIPHER_TKIP BIT(3)
|
|
#define ATBM_WPA_CIPHER_CCMP BIT(4)
|
|
#define ATBM_WPA_CIPHER_AES_128_CMAC BIT(5)
|
|
#define ATBM_WPA_CIPHER_GCMP BIT(6)
|
|
#define ATBM_WPA_CIPHER_SMS4 BIT(7)
|
|
|
|
|
|
#define ATBM_WPA_KEY_MGMT_IEEE8021X BIT(0)
|
|
#define ATBM_WPA_KEY_MGMT_PSK BIT(1)
|
|
#define ATBM_WPA_KEY_MGMT_NONE BIT(2)
|
|
#define ATBM_WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
|
|
#define ATBM_WPA_KEY_MGMT_WPA_NONE BIT(4)
|
|
#define ATBM_WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
|
|
#define ATBM_WPA_KEY_MGMT_FT_PSK BIT(6)
|
|
#define ATBM_WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
|
#define ATBM_WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
|
#define ATBM_WPA_KEY_MGMT_WPS BIT(9)
|
|
#define ATBM_WPA_KEY_MGMT_SAE BIT(10)
|
|
#define ATBM_WPA_KEY_MGMT_FT_SAE BIT(11)
|
|
#define ATBM_WPA_KEY_MGMT_WAPI_PSK BIT(12)
|
|
#define ATBM_WPA_KEY_MGMT_WAPI_CERT BIT(13)
|
|
#define ATBM_WPA_KEY_MGMT_CCKM BIT(14)
|
|
|
|
#define ATBM_OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)*/
|
|
#define ATBM_WMM_OUI_TYPE 2
|
|
#define ATBM_WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
|
#define ATBM_WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
|
|
#define ATBM_WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
|
|
|
|
#define ATBM_OUI_WFA 0x506f9a
|
|
#define ATBM_P2P_IE_VENDOR_TYPE 0x506f9a09
|
|
#define ATBM_WFD_IE_VENDOR_TYPE 0x506f9a0a
|
|
#define ATBM_WFD_OUI_TYPE 10
|
|
#define ATBM_HS20_IE_VENDOR_TYPE 0x506f9a10
|
|
#define ATBM_HS20_INDICATION_OUI_TYPE 16
|
|
|
|
#define ATBM_P2P_OUI_TYPE 9
|
|
#define ATBM_OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
|
|
|
#define ATBM_WPA_SELECTOR_LEN 4
|
|
#define ATBM_WPA_VERSION 1
|
|
#define ATBM_RSN_SELECTOR_LEN 4
|
|
#define ATBM_RSN_VERSION 1
|
|
|
|
static inline u32 ATBM_WPA_GET_BE24(const u8 *a)
|
|
{
|
|
return (a[0] << 16) | (a[1] << 8) | a[2];
|
|
}
|
|
|
|
static inline u32 ATBM_WPA_GET_BE32(const u8 *a)
|
|
{
|
|
return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
|
|
}
|
|
|
|
static inline u16 ATBM_WPA_GET_LE16(const u8 *a)
|
|
{
|
|
return (a[1] << 8) | a[0];
|
|
}
|
|
|
|
#define ATBM_RSN_CIPHER_SUITE_NONE 0x000fac00
|
|
#define ATBM_RSN_CIPHER_SUITE_WEP40 0x000fac01
|
|
#define ATBM_RSN_CIPHER_SUITE_TKIP 0x000fac02
|
|
#define ATBM_RSN_CIPHER_SUITE_CCMP 0x000fac04
|
|
#define ATBM_RSN_CIPHER_SUITE_WEP104 0x000fac05
|
|
#define ATBM_RSN_CIPHER_SUITE_AES_128_CMAC 0x000fac06
|
|
#define ATBM_RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED 0x000fac07
|
|
#define ATBM_RSN_CIPHER_SUITE_GCMP 0x000fac08
|
|
|
|
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_UNSPEC_802_1X 0x000fac01
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X 0x000fac02
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_FT_802_1X 0x000fac03
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_FT_PSK 0x000fac04
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_802_1X_SHA256 0x000fac05
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_PSK_SHA256 0x000fac06
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE 0x000fac07
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_SAE 0x000fac08
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_FT_SAE 0x000fac09
|
|
#define ATBM_RSN_AUTH_KEY_MGMT_CCKM 0x00409600
|
|
|
|
/* AKM suite selectors */
|
|
#define ATBM_WLAN_AKM_SUITE_8021X 0x000FAC01
|
|
#define ATBM_WLAN_AKM_SUITE_PSK 0x000FAC02
|
|
#define ATBM_WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
|
|
#define ATBM_WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
|
|
#define ATBM_WLAN_AKM_SUITE_TDLS 0x000FAC07
|
|
#define ATBM_WLAN_AKM_SUITE_SAE 0x000FAC08
|
|
#define ATBM_WLAN_AKM_SUITE_FT_OVER_SAE 0x000FAC09
|
|
#define ATBM_WLAN_AKM_SUITE_802_1X_SUITE_B_192 0x000fac12
|
|
#define ATBM_WLAN_AKM_SUITE_FILS_SHA256 0x000fac14
|
|
#define ATBM_WLAN_AKM_SUITE_FILS_SHA384 0x000fac15
|
|
#define ATBM_WLAN_AKM_SUITE_FT_FILS_SHA256 0x000fac16
|
|
#define ATBM_WLAN_AKM_SUITE_FT_FILS_SHA384 0x000fac17
|
|
|
|
#define ATBM_PMKID_LEN 16
|
|
#define ATBM_PMK_LEN 32
|
|
#define ATBM_WPA_REPLAY_COUNTER_LEN 8
|
|
#define ATBM_WPA_NONCE_LEN 32
|
|
#define ATBM_WPA_KEY_RSC_LEN 8
|
|
#define ATBM_WPA_GMK_LEN 32
|
|
#define ATBM_WPA_GTK_MAX_LEN 32
|
|
|
|
|
|
#define ATBM_WPA_AUTH_KEY_MGMT_NONE 0x0050f200
|
|
#define ATBM_WPA_AUTH_KEY_MGMT_UNSPEC_802_1X 0x0050f201
|
|
#define ATBM_WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X 0x0050f202
|
|
#define ATBM_WPA_AUTH_KEY_MGMT_CCKM 0x00409600
|
|
#define ATBM_WPA_CIPHER_SUITE_NONE 0x0050f200
|
|
#define ATBM_WPA_CIPHER_SUITE_WEP40 0x0050f201
|
|
#define ATBM_WPA_CIPHER_SUITE_TKIP 0x0050f202
|
|
#define ATBM_WPA_CIPHER_SUITE_CCMP 0x0050f204
|
|
#define ATBM_WPA_CIPHER_SUITE_WEP104 0x0050f205
|
|
|
|
#define ATBM_PRIVATE_OUI 0x4154424D
|
|
enum atbm_p2p_attr_id {
|
|
ATBM_P2P_ATTR_STATUS = 0,
|
|
ATBM_P2P_ATTR_MINOR_REASON_CODE = 1,
|
|
ATBM_P2P_ATTR_CAPABILITY = 2,
|
|
ATBM_P2P_ATTR_DEVICE_ID = 3,
|
|
ATBM_P2P_ATTR_GROUP_OWNER_INTENT = 4,
|
|
ATBM_P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
|
|
ATBM_P2P_ATTR_LISTEN_CHANNEL = 6,
|
|
ATBM_P2P_ATTR_GROUP_BSSID = 7,
|
|
ATBM_P2P_ATTR_EXT_LISTEN_TIMING = 8,
|
|
ATBM_P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
|
|
ATBM_P2P_ATTR_MANAGEABILITY = 10,
|
|
ATBM_P2P_ATTR_CHANNEL_LIST = 11,
|
|
ATBM_P2P_ATTR_NOTICE_OF_ABSENCE = 12,
|
|
ATBM_P2P_ATTR_DEVICE_INFO = 13,
|
|
ATBM_P2P_ATTR_GROUP_INFO = 14,
|
|
ATBM_P2P_ATTR_GROUP_ID = 15,
|
|
ATBM_P2P_ATTR_INTERFACE = 16,
|
|
ATBM_P2P_ATTR_OPERATING_CHANNEL = 17,
|
|
ATBM_P2P_ATTR_INVITATION_FLAGS = 18,
|
|
ATBM_P2P_ATTR_VENDOR_SPECIFIC = 221
|
|
};
|
|
|
|
/* P2P public action frames */
|
|
enum atbm_p2p_action_frame_type {
|
|
ATBM_P2P_GO_NEG_REQ = 0,
|
|
ATBM_P2P_GO_NEG_RESP = 1,
|
|
ATBM_P2P_GO_NEG_CONF = 2,
|
|
ATBM_P2P_INVITATION_REQ = 3,
|
|
ATBM_P2P_INVITATION_RESP = 4,
|
|
ATBM_P2P_DEV_DISC_REQ = 5,
|
|
ATBM_P2P_DEV_DISC_RESP = 6,
|
|
ATBM_P2P_PROV_DISC_REQ = 7,
|
|
ATBM_P2P_PROV_DISC_RESP = 8
|
|
};
|
|
struct atbm_p2p_message {
|
|
u8 dialog_token;
|
|
|
|
u8 *capability;
|
|
u8 *go_intent;
|
|
u8 *status;
|
|
u8 *operating_channel;
|
|
u8 *channel_list;
|
|
u8 channel_list_len;
|
|
|
|
u8 *group_bssid;
|
|
u8 *invitation_flags;
|
|
|
|
u8 *group_info;
|
|
size_t group_info_len;
|
|
|
|
u8 *group_id;
|
|
size_t group_id_len;
|
|
|
|
u8 *device_id;
|
|
|
|
u8 *manageability;
|
|
u8 *intended_addr;
|
|
};
|
|
|
|
struct atbm_ieee80211_vendor_ie {
|
|
u8 element_id;
|
|
u8 len;
|
|
u8 oui[3];
|
|
u8 oui_type;
|
|
} __packed;
|
|
|
|
struct atbm_ieee80211_mgmt {
|
|
__le16 frame_control;
|
|
__le16 duration;
|
|
u8 da[6];
|
|
u8 sa[6];
|
|
u8 bssid[6];
|
|
__le16 seq_ctrl;
|
|
union {
|
|
struct {
|
|
__le16 auth_alg;
|
|
__le16 auth_transaction;
|
|
__le16 status_code;
|
|
/* possibly followed by Challenge text */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) auth;
|
|
struct {
|
|
__le16 reason_code;
|
|
} __attribute__ ((packed)) deauth;
|
|
struct {
|
|
__le16 capab_info;
|
|
__le16 listen_interval;
|
|
/* followed by SSID and Supported rates */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) assoc_req;
|
|
struct {
|
|
__le16 capab_info;
|
|
__le16 status_code;
|
|
__le16 aid;
|
|
/* followed by Supported rates */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) assoc_resp, reassoc_resp;
|
|
struct {
|
|
__le16 capab_info;
|
|
__le16 listen_interval;
|
|
u8 current_ap[6];
|
|
/* followed by SSID and Supported rates */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) reassoc_req;
|
|
struct {
|
|
__le16 reason_code;
|
|
} __attribute__ ((packed)) disassoc;
|
|
struct {
|
|
__le64 timestamp;
|
|
__le16 beacon_int;
|
|
__le16 capab_info;
|
|
/* followed by some of SSID, Supported rates,
|
|
* FH Params, DS Params, CF Params, IBSS Params, TIM */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) beacon;
|
|
struct {
|
|
/* only variable items: SSID, Supported rates */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) probe_req;
|
|
struct {
|
|
__le64 timestamp;
|
|
__le16 beacon_int;
|
|
__le16 capab_info;
|
|
/* followed by some of SSID, Supported rates,
|
|
* FH Params, DS Params, CF Params, IBSS Params */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) probe_resp;
|
|
struct {
|
|
u8 category;
|
|
union {
|
|
struct {
|
|
u8 action; /* 9 */
|
|
u8 oui[3];
|
|
/* Vendor-specific content */
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) vs_public_action;
|
|
struct {
|
|
u8 action_code;
|
|
u8 dialog_token;
|
|
u8 status_code;
|
|
u8 variable[0];
|
|
} __attribute__ ((packed)) wme_action;
|
|
struct{
|
|
u8 action_code;
|
|
u8 dialog_token;
|
|
__le16 capab;
|
|
__le16 timeout;
|
|
__le16 start_seq_num;
|
|
} __attribute__((packed)) addba_req;
|
|
struct{
|
|
u8 action_code;
|
|
u8 dialog_token;
|
|
__le16 status;
|
|
__le16 capab;
|
|
__le16 timeout;
|
|
} __attribute__((packed)) addba_resp;
|
|
struct{
|
|
u8 action_code;
|
|
__le16 params;
|
|
__le16 reason_code;
|
|
} __attribute__((packed)) delba;
|
|
struct {
|
|
u8 action_code;
|
|
u8 variable[0];
|
|
} __attribute__((packed)) self_prot;
|
|
struct{
|
|
u8 action_code;
|
|
u8 variable[0];
|
|
} __attribute__((packed)) mesh_action;
|
|
struct {
|
|
u8 action;
|
|
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
|
} __attribute__ ((packed)) sa_query;
|
|
struct {
|
|
u8 action;
|
|
u8 smps_control;
|
|
} __attribute__ ((packed)) ht_smps;
|
|
struct {
|
|
u8 action_code;
|
|
u8 dialog_token;
|
|
__le16 capability;
|
|
u8 variable[0];
|
|
} __packed tdls_discover_resp;
|
|
} u;
|
|
} __attribute__ ((packed)) action;
|
|
} u;
|
|
} __attribute__ ((packed));
|
|
|
|
|
|
#ifndef WLAN_EXT_CAPA5_TDLS_ENABLED
|
|
#define WLAN_EXT_CAPA5_TDLS_ENABLED BIT(5)
|
|
#endif
|
|
#ifndef WLAN_TDLS_SNAP_RFTYPE
|
|
#define WLAN_TDLS_SNAP_RFTYPE 0x2
|
|
#endif
|
|
/**
|
|
* DOC: Introduction
|
|
*
|
|
* mac80211 is the Linux stack for 802.11 hardware that implements
|
|
* only partial functionality in hard- or firmware. This document
|
|
* defines the interface between mac80211 and low-level hardware
|
|
* drivers.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Calling mac80211 from interrupts
|
|
*
|
|
* Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
|
|
* called in hardware interrupt context. The low-level driver must not call any
|
|
* other functions in hardware interrupt context. If there is a need for such
|
|
* call, the low-level driver should first ACK the interrupt and perform the
|
|
* IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
|
|
* tasklet function.
|
|
*
|
|
* NOTE: If the driver opts to use the _irqsafe() functions, it may not also
|
|
* use the non-IRQ-safe functions!
|
|
*/
|
|
|
|
/**
|
|
* DOC: Warning
|
|
*
|
|
* If you're reading this document and not the header file itself, it will
|
|
* be incomplete because not all documentation has been converted yet.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Frame format
|
|
*
|
|
* As a general rule, when frames are passed between mac80211 and the driver,
|
|
* they start with the IEEE 802.11 header and include the same octets that are
|
|
* sent over the air except for the FCS which should be calculated by the
|
|
* hardware.
|
|
*
|
|
* There are, however, various exceptions to this rule for advanced features:
|
|
*
|
|
* The first exception is for hardware encryption and decryption offload
|
|
* where the IV/ICV may or may not be generated in hardware.
|
|
*
|
|
* Secondly, when the hardware handles fragmentation, the frame handed to
|
|
* the driver from mac80211 is the MSDU, not the MPDU.
|
|
*
|
|
* Finally, for received frames, the driver is able to indicate that it has
|
|
* filled a radiotap header and put that in front of the frame; if it does
|
|
* not do so then mac80211 may add this under certain circumstances.
|
|
*/
|
|
|
|
/**
|
|
* DOC: mac80211 workqueue
|
|
*
|
|
* mac80211 provides its own workqueue for drivers and internal mac80211 use.
|
|
* The workqueue is a single threaded workqueue and can only be accessed by
|
|
* helpers for sanity checking. Drivers must ensure all work added onto the
|
|
* mac80211 workqueue should be cancelled on the driver stop() callback.
|
|
*
|
|
* mac80211 will flushed the workqueue upon interface removal and during
|
|
* suspend.
|
|
*
|
|
* All work performed on the mac80211 workqueue must not acquire the RTNL lock.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* enum ieee80211_max_queues - maximum number of queues
|
|
*
|
|
* @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
|
|
*/
|
|
enum ieee80211_max_queues {
|
|
IEEE80211_MAX_QUEUES = 16,
|
|
};
|
|
|
|
#define IEEE80211_INVAL_HW_QUEUE 0xff
|
|
|
|
/**
|
|
* enum ieee80211_ac_numbers - AC numbers as used in mac80211
|
|
* @IEEE80211_AC_VO: voice
|
|
* @IEEE80211_AC_VI: video
|
|
* @IEEE80211_AC_BE: best effort
|
|
* @IEEE80211_AC_BK: background
|
|
*/
|
|
enum ieee80211_ac_numbers {
|
|
IEEE80211_AC_VO = 0,
|
|
IEEE80211_AC_VI = 1,
|
|
IEEE80211_AC_BE = 2,
|
|
IEEE80211_AC_BK = 3,
|
|
};
|
|
|
|
/**
|
|
* enum atbmwifi_ieee80211_ac_numbers - AC numbers as used in mac80211
|
|
* @IEEE80211_AC_VO: voice
|
|
* @IEEE80211_AC_VI: video
|
|
* @IEEE80211_AC_BE: best effort
|
|
* @IEEE80211_AC_BK: background
|
|
*/
|
|
enum atbmwifi_ieee80211_ac_numbers {
|
|
ATBM_IEEE80211_AC_VO = 0,
|
|
ATBM_IEEE80211_AC_VI = 1,
|
|
ATBM_IEEE80211_AC_BE = 2,
|
|
ATBM_IEEE80211_AC_BK = 3,
|
|
};
|
|
|
|
#define IEEE80211_NUM_ACS 4
|
|
|
|
/**
|
|
* struct ieee80211_tx_queue_params - transmit queue configuration
|
|
*
|
|
* The information provided in this structure is required for QoS
|
|
* transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
|
|
*
|
|
* @aifs: arbitration interframe space [0..255]
|
|
* @cw_min: minimum contention window [a value of the form
|
|
* 2^n-1 in the range 1..32767]
|
|
* @cw_max: maximum contention window [like @cw_min]
|
|
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
|
|
* @uapsd: is U-APSD mode enabled for the queue
|
|
*/
|
|
struct ieee80211_tx_queue_params {
|
|
u16 txop;
|
|
u16 cw_min;
|
|
u16 cw_max;
|
|
u8 aifs;
|
|
bool uapsd;
|
|
};
|
|
|
|
struct ieee80211_low_level_stats {
|
|
unsigned int dot11ACKFailureCount;
|
|
unsigned int dot11RTSFailureCount;
|
|
unsigned int dot11FCSErrorCount;
|
|
unsigned int dot11RTSSuccessCount;
|
|
};
|
|
|
|
/**
|
|
* enum ieee80211_bss_change - BSS change notification flags
|
|
*
|
|
* These flags are used with the bss_info_changed() callback
|
|
* to indicate which BSS parameter changed.
|
|
*
|
|
* @BSS_CHANGED_ASSOC: association status changed (associated/disassociated),
|
|
* also implies a change in the AID.
|
|
* @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
|
|
* @BSS_CHANGED_ERP_PREAMBLE: preamble changed
|
|
* @BSS_CHANGED_ERP_SLOT: slot timing changed
|
|
* @BSS_CHANGED_HT: 802.11n parameters changed
|
|
* @BSS_CHANGED_BASIC_RATES: Basic rateset changed
|
|
* @BSS_CHANGED_BEACON_INT: Beacon interval changed
|
|
* @BSS_CHANGED_BSSID: BSSID changed, for whatever
|
|
* reason (IBSS and managed mode)
|
|
* @BSS_CHANGED_BEACON: Beacon data changed, retrieve
|
|
* new beacon (beaconing modes)
|
|
* @BSS_CHANGED_BEACON_ENABLED: Beaconing should be
|
|
* enabled/disabled (beaconing modes)
|
|
* @BSS_CHANGED_CQM: Connection quality monitor config changed
|
|
* @BSS_CHANGED_IBSS: IBSS join status changed
|
|
* @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
|
|
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
|
|
* that it is only ever disabled for station mode.
|
|
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
|
|
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
|
|
* @BSS_CHANGED_PS: the PS flag or dynamic PS timeout changed
|
|
* @BSS_CHANGED_CHANNEL: vif channel changed
|
|
* @BSS_CHANGED_P2P_PS: NOA parameters changed.
|
|
*/
|
|
enum ieee80211_bss_change {
|
|
BSS_CHANGED_ASSOC = 1<<0,
|
|
BSS_CHANGED_ERP_CTS_PROT = 1<<1,
|
|
BSS_CHANGED_ERP_PREAMBLE = 1<<2,
|
|
BSS_CHANGED_ERP_SLOT = 1<<3,
|
|
BSS_CHANGED_HT = 1<<4,
|
|
BSS_CHANGED_BASIC_RATES = 1<<5,
|
|
BSS_CHANGED_BEACON_INT = 1<<6,
|
|
BSS_CHANGED_BSSID = 1<<7,
|
|
BSS_CHANGED_BEACON = 1<<8,
|
|
BSS_CHANGED_BEACON_ENABLED = 1<<9,
|
|
BSS_CHANGED_CQM = 1<<10,
|
|
BSS_CHANGED_IBSS = 1<<11,
|
|
BSS_CHANGED_ARP_FILTER = 1<<12,
|
|
BSS_CHANGED_QOS = 1<<13,
|
|
BSS_CHANGED_IDLE = 1<<14,
|
|
BSS_CHANGED_SSID = 1<<15,
|
|
BSS_CHANGED_PS = 1<<16,
|
|
BSS_CHANGED_CHANNEL = 1<<17, // XXX: COMBO: should this be merged with _HT?
|
|
BSS_CHANGED_RETRY_LIMITS = 1<<18,
|
|
BSS_CHANGED_P2P_PS = 1<<19,
|
|
#ifdef IPV6_FILTERING
|
|
BSS_CHANGED_NDP_FILTER = 1<<20,
|
|
#endif /*IPV6_FILTERING*/
|
|
BSS_CHANGED_STA_RESTART = 1<<21,
|
|
/* when adding here, make sure to change ieee80211_reconfig */
|
|
};
|
|
|
|
/*
|
|
* The maximum number of IPv4 addresses listed for ARP filtering. If the number
|
|
* of addresses for an interface increase beyond this value, hardware ARP
|
|
* filtering will be disabled.
|
|
*/
|
|
#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
|
|
|
|
#ifdef IPV6_FILTERING
|
|
/*
|
|
* The maximum number of IPv6 addresses listed for NDP filtering. If the number
|
|
* of addresses for an interface increase beyond this value, hardware NDP
|
|
* filtering will be disabled.
|
|
*/
|
|
#define IEEE80211_BSS_NDP_ADDR_LIST_LEN 4
|
|
#endif /*IPV6_FILTERING*/
|
|
|
|
|
|
#define IEEE80211_TX_CTL_STBC_SHIFT 23
|
|
/* there are 40 bytes if you don't need the rateset to be kept */
|
|
#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
|
|
|
|
/* if you do need the rateset, then you have less space */
|
|
#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24
|
|
|
|
/* maximum number of rate stages */
|
|
#define IEEE80211_TX_MAX_RATES 5
|
|
/**
|
|
* enum mac80211_rx_flags - receive flags
|
|
*
|
|
* These flags are used with the @flag member of &struct ieee80211_rx_status.
|
|
* @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame.
|
|
* Use together with %RX_FLAG_MMIC_STRIPPED.
|
|
* @RX_FLAG_DECRYPTED: This frame was decrypted in hardware.
|
|
* @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame,
|
|
* verification has been done by the hardware.
|
|
* @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame.
|
|
* If this flag is set, the stack cannot do any replay detection
|
|
* hence the driver or hardware will have to do that.
|
|
* @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on
|
|
* the frame.
|
|
* @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
|
|
* the frame.
|
|
* @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
|
|
* field) is valid and contains the time the first symbol of the MPDU
|
|
* was received. This is useful in monitor mode and for proper IBSS
|
|
* merging.
|
|
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame
|
|
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
|
|
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
|
|
* @RX_FLAG_SHORT_GI: Short guard interval was used
|
|
*/
|
|
enum mac80211_rx_flags {
|
|
RX_FLAG_MMIC_ERROR = 1<<0,
|
|
RX_FLAG_DECRYPTED = 1<<1,
|
|
RX_FLAG_MMIC_STRIPPED = 1<<3,
|
|
RX_FLAG_IV_STRIPPED = 1<<4,
|
|
RX_FLAG_FAILED_FCS_CRC = 1<<5,
|
|
RX_FLAG_FAILED_PLCP_CRC = 1<<6,
|
|
RX_FLAG_MACTIME_MPDU = 1<<7,
|
|
RX_FLAG_SHORTPRE = 1<<8,
|
|
RX_FLAG_HT = 1<<9,
|
|
RX_FLAG_40MHZ = 1<<10,
|
|
RX_FLAG_SHORT_GI = 1<<11,
|
|
RX_FLAG_HW_CHKSUM_ERROR = 1<<12,
|
|
RX_FLAG_STA_LISTEN = 1<<13,
|
|
};
|
|
|
|
/**
|
|
* struct ieee80211_rx_status - receive status
|
|
*
|
|
* The low-level driver should provide this information (the subset
|
|
* supported by hardware) to the 802.11 code with each received
|
|
* frame, in the skb's control buffer (cb).
|
|
*
|
|
* @mactime: value in microseconds of the 64-bit Time Synchronization Function
|
|
* (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
|
|
* @band: the active band when this frame was received
|
|
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
|
|
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
|
* unspecified depending on the hardware capabilities flags
|
|
* @IEEE80211_HW_SIGNAL_*
|
|
* @antenna: antenna used
|
|
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
|
* HT rates are use (RX_FLAG_HT)
|
|
* @flag: %RX_FLAG_*
|
|
* @rx_flags: internal RX flags for mac80211
|
|
*/
|
|
struct ieee80211_rx_status {
|
|
u64 mactime;
|
|
enum ieee80211_band band;
|
|
int freq;
|
|
int signal;
|
|
int antenna;
|
|
int rate_idx;
|
|
int flag;
|
|
unsigned int rx_flags;
|
|
};
|
|
|
|
/**
|
|
* enum ieee80211_key_flags - key flags
|
|
*
|
|
* These flags are used for communication about keys between the driver
|
|
* and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
|
|
*
|
|
* @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
|
|
* that the STA this key will be used with could be using QoS.
|
|
* @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
|
|
* driver to indicate that it requires IV generation for this
|
|
* particular key.
|
|
* @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
|
|
* the driver for a TKIP key if it requires Michael MIC
|
|
* generation in software.
|
|
* @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
|
|
* that the key is pairwise rather then a shared key.
|
|
* @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
|
|
* CCMP key if it requires CCMP encryption of management frames (MFP) to
|
|
* be done in software.
|
|
*/
|
|
enum ieee80211_key_flags {
|
|
IEEE80211_KEY_FLAG_WMM_STA = 1<<0,
|
|
IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1,
|
|
IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
|
|
IEEE80211_KEY_FLAG_PAIRWISE = 1<<3,
|
|
IEEE80211_KEY_FLAG_SW_MGMT = 1<<4,
|
|
IEEE80211_KEY_FLAG_ALLOC_IV = 1<<5,
|
|
};
|
|
|
|
/**
|
|
* struct ieee80211_key_conf - key information
|
|
*
|
|
* This key information is given by mac80211 to the driver by
|
|
* the set_key() callback in &struct ieee80211_ops.
|
|
*
|
|
* @hw_key_idx: To be set by the driver, this is the key index the driver
|
|
* wants to be given when a frame is transmitted and needs to be
|
|
* encrypted in hardware.
|
|
* @cipher: The key's cipher suite selector.
|
|
* @flags: key flags, see &enum ieee80211_key_flags.
|
|
* @keyidx: the key index (0-3)
|
|
* @keylen: key material length
|
|
* @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte)
|
|
* data block:
|
|
* - Temporal Encryption Key (128 bits)
|
|
* - Temporal Authenticator Tx MIC Key (64 bits)
|
|
* - Temporal Authenticator Rx MIC Key (64 bits)
|
|
* @icv_len: The ICV length for this key type
|
|
* @iv_len: The IV length for this key type
|
|
*/
|
|
struct ieee80211_key_conf {
|
|
u32 cipher;
|
|
u8 icv_len;
|
|
u8 iv_len;
|
|
u8 hw_key_idx;
|
|
u8 flags;
|
|
s8 keyidx;
|
|
u8 keylen;
|
|
u8 key[0];
|
|
};
|
|
|
|
/**
|
|
* struct ieee80211_sta - station table entry
|
|
*
|
|
* A station table entry represents a station we are possibly
|
|
* communicating with. Since stations are RCU-managed in
|
|
* mac80211, any ieee80211_sta pointer you get access to must
|
|
* either be protected by rcu_read_lock() explicitly or implicitly,
|
|
* or you must take good care to not use such a pointer after a
|
|
* call to your sta_remove callback that removed it.
|
|
*
|
|
* @addr: MAC address
|
|
* @aid: AID we assigned to the station if we're an AP
|
|
* @supp_rates: Bitmap of supported rates (per band)
|
|
* @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
|
|
* @wme: indicates whether the STA supports WME. Only valid during AP-mode.
|
|
* @drv_priv: data area for driver use, will always be aligned to
|
|
* sizeof(void *), size is determined in hw information.
|
|
* @uapsd_queues: bitmap of queues configured for uapsd. Only valid
|
|
* if wme is supported.
|
|
* @max_sp: max Service Period. Only valid if wme is supported.
|
|
*/
|
|
struct ieee80211_sta {
|
|
u32 supp_rates[IEEE80211_NUM_BANDS];
|
|
u8 addr[ETH_ALEN];
|
|
u16 aid;
|
|
struct ieee80211_sta_ht_cap ht_cap;
|
|
bool wme;
|
|
u8 uapsd_queues;
|
|
u8 max_sp;
|
|
struct atbm_wpa_ie_data wpa_sta_data;
|
|
};
|
|
|
|
|
|
/**
|
|
* enum ieee80211_hw_flags - hardware flags
|
|
*
|
|
* These flags are used to indicate hardware capabilities to
|
|
* the stack. Generally, flags here should have their meaning
|
|
* done in a way that the simplest hardware doesn't need setting
|
|
* any particular flags. There are some exceptions to this rule,
|
|
* however, so you are advised to review these flags carefully.
|
|
*
|
|
* @IEEE80211_HW_HAS_RATE_CONTROL:
|
|
* The hardware or firmware includes rate control, and cannot be
|
|
* controlled by the stack. As such, no rate control algorithm
|
|
* should be instantiated, and the TX rate reported to userspace
|
|
* will be taken from the TX status instead of the rate control
|
|
* algorithm.
|
|
* Note that this requires that the driver implement a number of
|
|
* callbacks so it has the correct information, it needs to have
|
|
* the @set_rts_threshold callback and must look at the BSS config
|
|
* @use_cts_prot for G/N protection, @use_short_slot for slot
|
|
* timing in 2.4 GHz and @use_short_preamble for preambles for
|
|
* CCK frames.
|
|
*
|
|
* @IEEE80211_HW_RX_INCLUDES_FCS:
|
|
* Indicates that received frames passed to the stack include
|
|
* the FCS at the end.
|
|
*
|
|
* @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING:
|
|
* Some wireless LAN chipsets buffer broadcast/multicast frames
|
|
* for power saving stations in the hardware/firmware and others
|
|
* rely on the host system for such buffering. This option is used
|
|
* to configure the IEEE 802.11 upper layer to buffer broadcast and
|
|
* multicast frames when there are power saving stations so that
|
|
* the driver can fetch them with ieee80211_get_buffered_bc().
|
|
*
|
|
* @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
|
|
* Hardware is not capable of short slot operation on the 2.4 GHz band.
|
|
*
|
|
* @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
|
|
* Hardware is not capable of receiving frames with short preamble on
|
|
* the 2.4 GHz band.
|
|
*
|
|
* @IEEE80211_HW_SIGNAL_UNSPEC:
|
|
* Hardware can provide signal values but we don't know its units. We
|
|
* expect values between 0 and @max_signal.
|
|
* If possible please provide dB or dBm instead.
|
|
*
|
|
* @IEEE80211_HW_SIGNAL_DBM:
|
|
* Hardware gives signal values in dBm, decibel difference from
|
|
* one milliwatt. This is the preferred method since it is standardized
|
|
* between different devices. @max_signal does not need to be set.
|
|
*
|
|
* @IEEE80211_HW_SPECTRUM_MGMT:
|
|
* Hardware supports spectrum management defined in 802.11h
|
|
* Measurement, Channel Switch, Quieting, TPC
|
|
*
|
|
* @IEEE80211_HW_AMPDU_AGGREGATION:
|
|
* Hardware supports 11n A-MPDU aggregation.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_PS:
|
|
* Hardware has power save support (i.e. can go to sleep).
|
|
*
|
|
* @IEEE80211_HW_PS_NULLFUNC_STACK:
|
|
* Hardware requires nullfunc frame handling in stack, implies
|
|
* stack support for dynamic PS.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_DYNAMIC_PS:
|
|
* Hardware has support for dynamic PS.
|
|
*
|
|
* @IEEE80211_HW_MFP_CAPABLE:
|
|
* Hardware supports management frame protection (MFP, IEEE 802.11w).
|
|
*
|
|
* @IEEE80211_HW_BEACON_FILTER:
|
|
* Hardware supports dropping of irrelevant beacon frames to
|
|
* avoid waking up cpu.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_STATIC_SMPS:
|
|
* Hardware supports static spatial multiplexing powersave,
|
|
* ie. can turn off all but one chain even on HT connections
|
|
* that should be using more chains.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS:
|
|
* Hardware supports dynamic spatial multiplexing powersave,
|
|
* ie. can turn off all but one chain and then wake the rest
|
|
* up as required after, for example, rts/cts handshake.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_UAPSD:
|
|
* Hardware supports Unscheduled Automatic Power Save Delivery
|
|
* (U-APSD) in managed mode. The mode is configured with
|
|
* conf_tx() operation.
|
|
*
|
|
* @IEEE80211_HW_REPORTS_TX_ACK_STATUS:
|
|
* Hardware can provide ack status reports of Tx frames to
|
|
* the stack.
|
|
*
|
|
* @IEEE80211_HW_CONNECTION_MONITOR:
|
|
* The hardware performs its own connection monitoring, including
|
|
* periodic keep-alives to the AP and probing the AP on beacon loss.
|
|
* When this flag is set, signaling beacon-loss will cause an immediate
|
|
* change to disassociated state.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_CQM_RSSI:
|
|
* Hardware can do connection quality monitoring - i.e. it can monitor
|
|
* connection quality related parameters, such as the RSSI level and
|
|
* provide notifications if configured trigger levels are reached.
|
|
*
|
|
* @IEEE80211_HW_NEED_DTIM_PERIOD:
|
|
* This device needs to know the DTIM period for the BSS before
|
|
* associating.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports
|
|
* per-station GTKs as used by IBSS RSN or during fast transition. If
|
|
* the device doesn't support per-station GTKs, but can be asked not
|
|
* to decrypt group addressed frames, then IBSS RSN support is still
|
|
* possible but software crypto will be used. Advertise the wiphy flag
|
|
* only in that case.
|
|
*
|
|
* @IEEE80211_HW_AP_LINK_PS: When operating in AP mode the device
|
|
* autonomously manages the PS status of connected stations. When
|
|
* this flag is set mac80211 will not trigger PS mode for connected
|
|
* stations based on the PM bit of incoming frames.
|
|
* Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
|
|
* the PS mode of connected stations.
|
|
*
|
|
* @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session
|
|
* setup strictly in HW. mac80211 should not attempt to do this in
|
|
* software.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_CQM_BEACON_MISS
|
|
* Connection quality monitoring - beacon miss.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_CQM_TX_FAIL
|
|
* Connection quality monitoring - tx failure.
|
|
*
|
|
* @IEEE80211_HW_SUPPORTS_MULTI_CHANNEL
|
|
* Hardware supports simultaneous operation on different channels.
|
|
*
|
|
* @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface
|
|
* queue mapping in order to use different queues (not just one per AC)
|
|
* for different virtual interfaces. See the doc section on HW queue
|
|
* control for more details.
|
|
*/
|
|
enum ieee80211_hw_flags {
|
|
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
|
|
IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
|
|
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
|
|
IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
|
|
IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
|
|
IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
|
|
IEEE80211_HW_SIGNAL_DBM = 1<<6,
|
|
IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7,
|
|
IEEE80211_HW_SPECTRUM_MGMT = 1<<8,
|
|
IEEE80211_HW_AMPDU_AGGREGATION = 1<<9,
|
|
IEEE80211_HW_SUPPORTS_PS = 1<<10,
|
|
IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11,
|
|
IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
|
|
IEEE80211_HW_MFP_CAPABLE = 1<<13,
|
|
IEEE80211_HW_BEACON_FILTER = 1<<14,
|
|
IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15,
|
|
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16,
|
|
IEEE80211_HW_SUPPORTS_UAPSD = 1<<17,
|
|
IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
|
|
IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
|
|
IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20,
|
|
IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21,
|
|
IEEE80211_HW_AP_LINK_PS = 1<<22,
|
|
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
|
|
IEEE80211_HW_SUPPORTS_CQM_BEACON_MISS = 1<<24,
|
|
IEEE80211_HW_SUPPORTS_CQM_TX_FAIL = 1<<25,
|
|
IEEE80211_HW_SUPPORTS_P2P_PS = 1<<26,
|
|
IEEE80211_HW_SUPPORTS_MULTI_CHANNEL = 1<<27,
|
|
IEEE80211_HW_QUEUE_CONTROL = 1<<28,
|
|
};
|
|
|
|
/**
|
|
* struct ieee80211_hw - hardware information and state
|
|
*
|
|
* This structure contains the configuration and hardware
|
|
* information for an 802.11 PHY.
|
|
*
|
|
* @wiphy: This points to the &struct wiphy allocated for this
|
|
* 802.11 PHY. You must fill in the @perm_addr and @dev
|
|
* members of this structure using SET_IEEE80211_DEV()
|
|
* and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
|
|
* bands (with channels, bitrates) are registered here.
|
|
*
|
|
* @conf: &struct ieee80211_conf, device configuration, don't use.
|
|
*
|
|
* @priv: pointer to private area that was allocated for driver use
|
|
* along with this structure.
|
|
*
|
|
* @flags: hardware flags, see &enum ieee80211_hw_flags.
|
|
*
|
|
* @extra_tx_headroom: headroom to reserve in each transmit skb
|
|
* for use by the driver (e.g. for transmit headers.)
|
|
*
|
|
* @channel_change_time: time (in microseconds) it takes to change channels.
|
|
*
|
|
* @max_signal: Maximum value for signal (rssi) in RX information, used
|
|
* only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
|
|
*
|
|
* @max_listen_interval: max listen interval in units of beacon interval
|
|
* that HW supports
|
|
*
|
|
* @queues: number of available hardware transmit queues for
|
|
* data packets. WMM/QoS requires at least four, these
|
|
* queues need to have configurable access parameters.
|
|
*
|
|
* @rate_control_algorithm: rate control algorithm for this hardware.
|
|
* If unset (NULL), the default algorithm will be used. Must be
|
|
* set before calling ieee80211_register_hw().
|
|
*
|
|
* @vif_data_size: size (in bytes) of the drv_priv data area
|
|
* within &struct ieee80211_vif.
|
|
* @sta_data_size: size (in bytes) of the drv_priv data area
|
|
* within &struct ieee80211_sta.
|
|
*
|
|
* @max_rates: maximum number of alternate rate retry stages the hw
|
|
* can handle.
|
|
* @max_report_rates: maximum number of alternate rate retry stages
|
|
* the hw can report back.
|
|
* @max_rate_tries: maximum number of tries for each stage
|
|
*
|
|
* @napi_weight: weight used for NAPI polling. You must specify an
|
|
* appropriate value here if a napi_poll operation is provided
|
|
* by your driver.
|
|
*
|
|
* @max_rx_aggregation_subframes: maximum buffer size (number of
|
|
* sub-frames) to be used for A-MPDU block ack receiver
|
|
* aggregation.
|
|
* This is only relevant if the device has restrictions on the
|
|
* number of subframes, if it relies on mac80211 to do reordering
|
|
* it shouldn't be set.
|
|
*
|
|
* @max_tx_aggregation_subframes: maximum number of subframes in an
|
|
* aggregate an HT driver will transmit, used by the peer as a
|
|
* hint to size its reorder buffer.
|
|
*
|
|
* @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX
|
|
* (if %IEEE80211_HW_QUEUE_CONTROL is set)
|
|
*/
|
|
/**
|
|
* DOC: Hardware crypto acceleration
|
|
*
|
|
* mac80211 is capable of taking advantage of many hardware
|
|
* acceleration designs for encryption and decryption operations.
|
|
*
|
|
* The set_key() callback in the &struct ieee80211_ops for a given
|
|
* device is called to enable hardware acceleration of encryption and
|
|
* decryption. The callback takes a @sta parameter that will be NULL
|
|
* for default keys or keys used for transmission only, or point to
|
|
* the station information for the peer for individual keys.
|
|
* Multiple transmission keys with the same key index may be used when
|
|
* VLANs are configured for an access point.
|
|
*
|
|
* When transmitting, the TX control data will use the @hw_key_idx
|
|
* selected by the driver by modifying the &struct ieee80211_key_conf
|
|
* pointed to by the @key parameter to the set_key() function.
|
|
*
|
|
* The set_key() call for the %SET_KEY command should return 0 if
|
|
* the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be
|
|
* added; if you return 0 then hw_key_idx must be assigned to the
|
|
* hardware key index, you are free to use the full u8 range.
|
|
*
|
|
* When the cmd is %DISABLE_KEY then it must succeed.
|
|
*
|
|
* Note that it is permissible to not decrypt a frame even if a key
|
|
* for it has been uploaded to hardware, the stack will not make any
|
|
* decision based on whether a key has been uploaded or not but rather
|
|
* based on the receive flags.
|
|
*
|
|
* The &struct ieee80211_key_conf structure pointed to by the @key
|
|
* parameter is guaranteed to be valid until another call to set_key()
|
|
* removes it, but it can only be used as a cookie to differentiate
|
|
* keys.
|
|
*
|
|
* In TKIP some HW need to be provided a phase 1 key, for RX decryption
|
|
* acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
|
|
* handler.
|
|
* The update_tkip_key() call updates the driver with the new phase 1 key.
|
|
* This happens every time the iv16 wraps around (every 65536 packets). The
|
|
* set_key() call will happen only once for each key (unless the AP did
|
|
* rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
|
|
* provided by update_tkip_key only. The trigger that makes mac80211 call this
|
|
* handler is software decryption with wrap around of iv16.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Powersave support
|
|
*
|
|
* mac80211 has support for various powersave implementations.
|
|
*
|
|
* First, it can support hardware that handles all powersaving by itself,
|
|
* such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS hardware
|
|
* flag. In that case, it will be told about the desired powersave mode
|
|
* with the %IEEE80211_CONF_PS flag depending on the association status.
|
|
* The hardware must take care of sending nullfunc frames when necessary,
|
|
* i.e. when entering and leaving powersave mode. The hardware is required
|
|
* to look at the AID in beacons and signal to the AP that it woke up when
|
|
* it finds traffic directed to it.
|
|
*
|
|
* %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in
|
|
* IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused
|
|
* with hardware wakeup and sleep states. Driver is responsible for waking
|
|
* up the hardware before issuing commands to the hardware and putting it
|
|
* back to sleep at appropriate times.
|
|
*
|
|
* When PS is enabled, hardware needs to wakeup for beacons and receive the
|
|
* buffered multicast/broadcast frames after the beacon. Also it must be
|
|
* possible to send frames and receive the acknowledment frame.
|
|
*
|
|
* Other hardware designs cannot send nullfunc frames by themselves and also
|
|
* need software support for parsing the TIM bitmap. This is also supported
|
|
* by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and
|
|
* %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still
|
|
* required to pass up beacons. The hardware is still required to handle
|
|
* waking up for multicast traffic; if it cannot the driver must handle that
|
|
* as best as it can, mac80211 is too slow to do that.
|
|
*
|
|
* Dynamic powersave is an extension to normal powersave in which the
|
|
* hardware stays awake for a user-specified period of time after sending a
|
|
* frame so that reply frames need not be buffered and therefore delayed to
|
|
* the next wakeup. It's compromise of getting good enough latency when
|
|
* there's data traffic and still saving significantly power in idle
|
|
* periods.
|
|
*
|
|
* Dynamic powersave is simply supported by mac80211 enabling and disabling
|
|
* PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS
|
|
* flag and mac80211 will handle everything automatically. Additionally,
|
|
* hardware having support for the dynamic PS feature may set the
|
|
* %IEEE80211_HW_SUPPORTS_DYNAMIC_PS flag to indicate that it can support
|
|
* dynamic PS mode itself. The driver needs to look at the
|
|
* @dynamic_ps_timeout hardware configuration value and use it that value
|
|
* whenever %IEEE80211_CONF_PS is set. In this case mac80211 will disable
|
|
* dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
|
|
* enabled whenever user has enabled powersave.
|
|
*
|
|
* Some hardware need to toggle a single shared antenna between WLAN and
|
|
* Bluetooth to facilitate co-existence. These types of hardware set
|
|
* limitations on the use of host controlled dynamic powersave whenever there
|
|
* is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
|
|
* driver may request temporarily going into full power save, in order to
|
|
* enable toggling the antenna between BT and WLAN. If the driver requests
|
|
* disabling dynamic powersave, the @dynamic_ps_timeout value will be
|
|
* temporarily set to zero until the driver re-enables dynamic powersave.
|
|
*
|
|
* Driver informs U-APSD client support by enabling
|
|
* %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
|
|
* uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
|
|
* Nullfunc frames and stay awake until the service period has ended. To
|
|
* utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
|
|
* from that AC are transmitted with powersave enabled.
|
|
*
|
|
* Note: U-APSD client mode is not yet supported with
|
|
* %IEEE80211_HW_PS_NULLFUNC_STACK.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Beacon filter support
|
|
*
|
|
* Some hardware have beacon filter support to reduce host cpu wakeups
|
|
* which will reduce system power consumption. It usuallly works so that
|
|
* the firmware creates a checksum of the beacon but omits all constantly
|
|
* changing elements (TSF, TIM etc). Whenever the checksum changes the
|
|
* beacon is forwarded to the host, otherwise it will be just dropped. That
|
|
* way the host will only receive beacons where some relevant information
|
|
* (for example ERP protection or WMM settings) have changed.
|
|
*
|
|
* Beacon filter support is advertised with the %IEEE80211_HW_BEACON_FILTER
|
|
* hardware capability. The driver needs to enable beacon filter support
|
|
* whenever power save is enabled, that is %IEEE80211_CONF_PS is set. When
|
|
* power save is enabled, the stack will not check for beacon loss and the
|
|
* driver needs to notify about loss of beacons with ieee80211_beacon_loss().
|
|
*
|
|
* The time (or number of beacons missed) until the firmware notifies the
|
|
* driver of a beacon loss event (which in turn causes the driver to call
|
|
* ieee80211_beacon_loss()) should be configurable and will be controlled
|
|
* by mac80211 and the roaming algorithm in the future.
|
|
*
|
|
* Since there may be constantly changing information elements that nothing
|
|
* in the software stack cares about, we will, in the future, have mac80211
|
|
* tell the driver which information elements are interesting in the sense
|
|
* that we want to see changes in them. This will include
|
|
* - a list of information element IDs
|
|
* - a list of OUIs for the vendor information element
|
|
*
|
|
* Ideally, the hardware would filter out any beacons without changes in the
|
|
* requested elements, but if it cannot support that it may, at the expense
|
|
* of some efficiency, filter out only a subset. For example, if the device
|
|
* doesn't support checking for OUIs it should pass up all changes in all
|
|
* vendor information elements.
|
|
*
|
|
* Note that change, for the sake of simplification, also includes information
|
|
* elements appearing or disappearing from the beacon.
|
|
*
|
|
* Some hardware supports an "ignore list" instead, just make sure nothing
|
|
* that was requested is on the ignore list, and include commonly changing
|
|
* information element IDs in the ignore list, for example 11 (BSS load) and
|
|
* the various vendor-assigned IEs with unknown contents (128, 129, 133-136,
|
|
* 149, 150, 155, 156, 173, 176, 178, 179, 219); for forward compatibility
|
|
* it could also include some currently unused IDs.
|
|
*
|
|
*
|
|
* In addition to these capabilities, hardware should support notifying the
|
|
* host of changes in the beacon RSSI. This is relevant to implement roaming
|
|
* when no traffic is flowing (when traffic is flowing we see the RSSI of
|
|
* the received data packets). This can consist in notifying the host when
|
|
* the RSSI changes significantly or when it drops below or rises above
|
|
* configurable thresholds. In the future these thresholds will also be
|
|
* configured by mac80211 (which gets them from userspace) to implement
|
|
* them as the roaming algorithm requires.
|
|
*
|
|
* If the hardware cannot implement this, the driver should ask it to
|
|
* periodically pass beacon frames to the host so that software can do the
|
|
* signal strength threshold checking.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Spatial multiplexing power save
|
|
*
|
|
* SMPS (Spatial multiplexing power save) is a mechanism to conserve
|
|
* power in an 802.11n implementation. For details on the mechanism
|
|
* and rationale, please refer to 802.11 (as amended by 802.11n-2009)
|
|
* "11.2.3 SM power save".
|
|
*
|
|
* The mac80211 implementation is capable of sending action frames
|
|
* to update the AP about the station's SMPS mode, and will instruct
|
|
* the driver to enter the specific mode. It will also announce the
|
|
* requested SMPS mode during the association handshake. Hardware
|
|
* support for this feature is required, and can be indicated by
|
|
* hardware flags.
|
|
*
|
|
* The default mode will be "automatic", which nl80211/cfg80211
|
|
* defines to be dynamic SMPS in (regular) powersave, and SMPS
|
|
* turned off otherwise.
|
|
*
|
|
* To support this feature, the driver must set the appropriate
|
|
* hardware support flags, and handle the SMPS flag to the config()
|
|
* operation. It will then with this mechanism be instructed to
|
|
* enter the requested SMPS mode while associated to an HT AP.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Frame filtering
|
|
*
|
|
* mac80211 requires to see many management frames for proper
|
|
* operation, and users may want to see many more frames when
|
|
* in monitor mode. However, for best CPU usage and power consumption,
|
|
* having as few frames as possible percolate through the stack is
|
|
* desirable. Hence, the hardware should filter as much as possible.
|
|
*
|
|
* To achieve this, mac80211 uses filter flags (see below) to tell
|
|
* the driver's configure_filter() function which frames should be
|
|
* passed to mac80211 and which should be filtered out.
|
|
*
|
|
* Before configure_filter() is invoked, the prepare_multicast()
|
|
* callback is invoked with the parameters @mc_count and @mc_list
|
|
* for the combined multicast address list of all virtual interfaces.
|
|
* It's use is optional, and it returns a u64 that is passed to
|
|
* configure_filter(). Additionally, configure_filter() has the
|
|
* arguments @changed_flags telling which flags were changed and
|
|
* @total_flags with the new flag states.
|
|
*
|
|
* If your device has no multicast address filters your driver will
|
|
* need to check both the %FIF_ALLMULTI flag and the @mc_count
|
|
* parameter to see whether multicast frames should be accepted
|
|
* or dropped.
|
|
*
|
|
* All unsupported flags in @total_flags must be cleared.
|
|
* Hardware does not support a flag if it is incapable of _passing_
|
|
* the frame to the stack. Otherwise the driver must ignore
|
|
* the flag, but not clear it.
|
|
* You must _only_ clear the flag (announce no support for the
|
|
* flag to mac80211) if you are not able to pass the packet type
|
|
* to the stack (so the hardware always filters it).
|
|
* So for example, you should clear @FIF_CONTROL, if your hardware
|
|
* always filters control frames. If your hardware always passes
|
|
* control frames to the kernel and is incapable of filtering them,
|
|
* you do _not_ clear the @FIF_CONTROL flag.
|
|
* This rule applies to all other FIF flags as well.
|
|
*/
|
|
|
|
/**
|
|
* DOC: AP support for powersaving clients
|
|
*
|
|
* In order to implement AP and P2P GO modes, mac80211 has support for
|
|
* client powersaving, both "legacy" PS (PS-Poll/null data) and uAPSD.
|
|
* There currently is no support for sAPSD.
|
|
*
|
|
* There is one assumption that mac80211 makes, namely that a client
|
|
* will not poll with PS-Poll and trigger with uAPSD at the same time.
|
|
* Both are supported, and both can be used by the same client, but
|
|
* they can't be used concurrently by the same client. This simplifies
|
|
* the driver code.
|
|
*
|
|
* The first thing to keep in mind is that there is a flag for complete
|
|
* driver implementation: %IEEE80211_HW_AP_LINK_PS. If this flag is set,
|
|
* mac80211 expects the driver to handle most of the state machine for
|
|
* powersaving clients and will ignore the PM bit in incoming frames.
|
|
* Drivers then use ieee80211_sta_ps_transition() to inform mac80211 of
|
|
* stations' powersave transitions. In this mode, mac80211 also doesn't
|
|
* handle PS-Poll/uAPSD.
|
|
*
|
|
* In the mode without %IEEE80211_HW_AP_LINK_PS, mac80211 will check the
|
|
* PM bit in incoming frames for client powersave transitions. When a
|
|
* station goes to sleep, we will stop transmitting to it. There is,
|
|
* however, a race condition: a station might go to sleep while there is
|
|
* data buffered on hardware queues. If the device has support for this
|
|
* it will reject frames, and the driver should give the frames back to
|
|
* mac80211 with the %IEEE80211_TX_STAT_TX_FILTERED flag set which will
|
|
* cause mac80211 to retry the frame when the station wakes up. The
|
|
* driver is also notified of powersave transitions by calling its
|
|
* @sta_notify callback.
|
|
*
|
|
* When the station is asleep, it has three choices: it can wake up,
|
|
* it can PS-Poll, or it can possibly start a uAPSD service period.
|
|
* Waking up is implemented by simply transmitting all buffered (and
|
|
* filtered) frames to the station. This is the easiest case. When
|
|
* the station sends a PS-Poll or a uAPSD trigger frame, mac80211
|
|
* will inform the driver of this with the @allow_buffered_frames
|
|
* callback; this callback is optional. mac80211 will then transmit
|
|
* the frames as usual and set the %IEEE80211_TX_CTL_POLL_RESPONSE
|
|
* on each frame. The last frame in the service period (or the only
|
|
* response to a PS-Poll) also has %IEEE80211_TX_STATUS_EOSP set to
|
|
* indicate that it ends the service period; as this frame must have
|
|
* TX status report it also sets %IEEE80211_TX_CTL_REQ_TX_STATUS.
|
|
* When TX status is reported for this frame, the service period is
|
|
* marked has having ended and a new one can be started by the peer.
|
|
*
|
|
* Another race condition can happen on some devices like iwlwifi
|
|
* when there are frames queued for the station and it wakes up
|
|
* or polls; the frames that are already queued could end up being
|
|
* transmitted first instead, causing reordering and/or wrong
|
|
* processing of the EOSP. The cause is that allowing frames to be
|
|
* transmitted to a certain station is out-of-band communication to
|
|
* the device. To allow this problem to be solved, the driver can
|
|
* call ieee80211_sta_block_awake() if frames are buffered when it
|
|
* is notified that the station went to sleep. When all these frames
|
|
* have been filtered (see above), it must call the function again
|
|
* to indicate that the station is no longer blocked.
|
|
*
|
|
* If the driver buffers frames in the driver for aggregation in any
|
|
* way, it must use the ieee80211_sta_set_buffered() call when it is
|
|
* notified of the station going to sleep to inform mac80211 of any
|
|
* TIDs that have frames buffered. Note that when a station wakes up
|
|
* this information is reset (hence the requirement to call it when
|
|
* informed of the station going to sleep). Then, when a service
|
|
* period starts for any reason, @release_buffered_frames is called
|
|
* with the number of frames to be released and which TIDs they are
|
|
* to come from. In this case, the driver is responsible for setting
|
|
* the EOSP (for uAPSD) and MORE_DATA bits in the released frames,
|
|
* to help the @more_data paramter is passed to tell the driver if
|
|
* there is more data on other TIDs -- the TIDs to release frames
|
|
* from are ignored since mac80211 doesn't know how many frames the
|
|
* buffers for those TIDs contain.
|
|
*
|
|
* If the driver also implement GO mode, where absence periods may
|
|
* shorten service periods (or abort PS-Poll responses), it must
|
|
* filter those response frames except in the case of frames that
|
|
* are buffered in the driver -- those must remain buffered to avoid
|
|
* reordering. Because it is possible that no frames are released
|
|
* in this case, the driver must call ieee80211_sta_eosp_irqsafe()
|
|
* to indicate to mac80211 that the service period ended anyway.
|
|
*
|
|
* Finally, if frames from multiple TIDs are released from mac80211
|
|
* but the driver might reorder them, it must clear & set the flags
|
|
* appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
|
|
* and also take care of the EOSP and MORE_DATA bits in the frame.
|
|
* The driver may also use ieee80211_sta_eosp_irqsafe() in this case.
|
|
*/
|
|
|
|
/**
|
|
* DOC: HW queue control
|
|
*
|
|
* Before HW queue control was introduced, mac80211 only had a single static
|
|
* assignment of per-interface AC software queues to hardware queues. This
|
|
* was problematic for a few reasons:
|
|
* 1) off-channel transmissions might get stuck behind other frames
|
|
* 2) multiple virtual interfaces couldn't be handled correctly
|
|
* 3) after-DTIM frames could get stuck behind other frames
|
|
*
|
|
* To solve this, hardware typically uses multiple different queues for all
|
|
* the different usages, and this needs to be propagated into mac80211 so it
|
|
* won't have the same problem with the software queues.
|
|
*
|
|
* Therefore, mac80211 now offers the %IEEE80211_HW_QUEUE_CONTROL capability
|
|
* flag that tells it that the driver implements its own queue control. To do
|
|
* so, the driver will set up the various queues in each &struct ieee80211_vif
|
|
* and the offchannel queue in &struct ieee80211_hw. In response, mac80211 will
|
|
* use those queue IDs in the hw_queue field of &struct ieee80211_tx_info and
|
|
* if necessary will queue the frame on the right software queue that mirrors
|
|
* the hardware queue.
|
|
* Additionally, the driver has to then use these HW queue IDs for the queue
|
|
* management functions (ieee80211_stop_queue() et al.)
|
|
*
|
|
* The driver is free to set up the queue mappings as needed, multiple virtual
|
|
* interfaces may map to the same hardware queues if needed. The setup has to
|
|
* happen during add_interface or change_interface callbacks. For example, a
|
|
* driver supporting station+station and station+AP modes might decide to have
|
|
* 10 hardware queues to handle different scenarios:
|
|
*
|
|
* 4 AC HW queues for 1st vif: 0, 1, 2, 3
|
|
* 4 AC HW queues for 2nd vif: 4, 5, 6, 7
|
|
* after-DTIM queue for AP: 8
|
|
* off-channel queue: 9
|
|
*
|
|
* It would then set up the hardware like this:
|
|
* hw.offchannel_tx_hw_queue = 9
|
|
*
|
|
* and the first virtual interface that is added as follows:
|
|
* vif.hw_queue[IEEE80211_AC_VO] = 0
|
|
* vif.hw_queue[IEEE80211_AC_VI] = 1
|
|
* vif.hw_queue[IEEE80211_AC_BE] = 2
|
|
* vif.hw_queue[IEEE80211_AC_BK] = 3
|
|
* vif.cab_queue = 8 // if AP mode, otherwise %IEEE80211_INVAL_HW_QUEUE
|
|
* and the second virtual interface with 4-7.
|
|
*
|
|
* If queue 6 gets full, for example, mac80211 would only stop the second
|
|
* virtual interface's BE queue since virtual interface queues are per AC.
|
|
*
|
|
* Note that the vif.cab_queue value should be set to %IEEE80211_INVAL_HW_QUEUE
|
|
* whenever the queue is not used (i.e. the interface is not in AP mode) if the
|
|
* queue could potentially be shared since mac80211 will look at cab_queue when
|
|
* a queue is stopped/woken even if the interface is not in AP mode.
|
|
*/
|
|
|
|
/**
|
|
* enum ieee80211_filter_flags - hardware filter flags
|
|
*
|
|
* These flags determine what the filter in hardware should be
|
|
* programmed to let through and what should not be passed to the
|
|
* stack. It is always safe to pass more frames than requested,
|
|
* but this has negative impact on power consumption.
|
|
*
|
|
* @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS,
|
|
* think of the BSS as your network segment and then this corresponds
|
|
* to the regular ethernet device promiscuous mode.
|
|
*
|
|
* @FIF_ALLMULTI: pass all multicast frames, this is used if requested
|
|
* by the user or if the hardware is not capable of filtering by
|
|
* multicast address.
|
|
*
|
|
* @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the
|
|
* %RX_FLAG_FAILED_FCS_CRC for them)
|
|
*
|
|
* @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set
|
|
* the %RX_FLAG_FAILED_PLCP_CRC for them
|
|
*
|
|
* @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate
|
|
* to the hardware that it should not filter beacons or probe responses
|
|
* by BSSID. Filtering them can greatly reduce the amount of processing
|
|
* mac80211 needs to do and the amount of CPU wakeups, so you should
|
|
* honour this flag if possible.
|
|
*
|
|
* @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
|
|
* is not set then only those addressed to this station.
|
|
*
|
|
* @FIF_OTHER_BSS: pass frames destined to other BSSes
|
|
*
|
|
* @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
|
|
* those addressed to this station.
|
|
*
|
|
* @FIF_PROBE_REQ: pass probe request frames
|
|
*/
|
|
enum ieee80211_filter_flags {
|
|
FIF_PROMISC_IN_BSS = 1<<0,
|
|
FIF_ALLMULTI = 1<<1,
|
|
FIF_FCSFAIL = 1<<2,
|
|
FIF_PLCPFAIL = 1<<3,
|
|
FIF_BCN_PRBRESP_PROMISC = 1<<4,
|
|
FIF_CONTROL = 1<<5,
|
|
FIF_OTHER_BSS = 1<<6,
|
|
FIF_PSPOLL = 1<<7,
|
|
FIF_PROBE_REQ = 1<<8,
|
|
};
|
|
|
|
/**
|
|
* enum ieee80211_ampdu_mlme_action - A-MPDU actions
|
|
*
|
|
* These flags are used with the ampdu_action() callback in
|
|
* &struct ieee80211_ops to indicate which action is needed.
|
|
*
|
|
* Note that drivers MUST be able to deal with a TX aggregation
|
|
* session being stopped even before they OK'ed starting it by
|
|
* calling ieee80211_start_tx_ba_cb_irqsafe, because the peer
|
|
* might receive the addBA frame and send a delBA right away!
|
|
*
|
|
* @IEEE80211_AMPDU_RX_START: start Rx aggregation
|
|
* @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
|
|
* @IEEE80211_AMPDU_TX_START: start Tx aggregation
|
|
* @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
|
|
* @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
|
|
*/
|
|
enum ieee80211_ampdu_mlme_action {
|
|
IEEE80211_AMPDU_RX_START,
|
|
IEEE80211_AMPDU_RX_STOP,
|
|
IEEE80211_AMPDU_TX_START,
|
|
IEEE80211_AMPDU_TX_STOP,
|
|
IEEE80211_AMPDU_TX_OPERATIONAL,
|
|
};
|
|
|
|
/**
|
|
* enum ieee80211_tx_sync_type - TX sync type
|
|
* @IEEE80211_TX_SYNC_AUTH: sync TX for authentication
|
|
* (and possibly also before direct probe)
|
|
* @IEEE80211_TX_SYNC_ASSOC: sync TX for association
|
|
* @IEEE80211_TX_SYNC_ACTION: sync TX for action frame
|
|
* (not implemented yet)
|
|
*/
|
|
enum ieee80211_tx_sync_type {
|
|
IEEE80211_TX_SYNC_AUTH,
|
|
IEEE80211_TX_SYNC_ASSOC,
|
|
IEEE80211_TX_SYNC_ACTION,
|
|
};
|
|
|
|
/**
|
|
* enum ieee80211_frame_release_type - frame release reason
|
|
* @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
|
|
* @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
|
|
* frame received on trigger-enabled AC
|
|
*/
|
|
enum ieee80211_frame_release_type {
|
|
IEEE80211_FRAME_RELEASE_PSPOLL,
|
|
IEEE80211_FRAME_RELEASE_UAPSD,
|
|
};
|
|
|
|
/*
|
|
* The TX headroom reserved by mac80211 for its own tx_status functions.
|
|
* This is enough for the radiotap header.
|
|
*/
|
|
#define IEEE80211_TX_STATUS_HEADROOM 14
|
|
|
|
struct atbm_ewma {
|
|
unsigned long internal;
|
|
unsigned long factor;
|
|
unsigned long weight;
|
|
};
|
|
static inline int atbm_ilog2(unsigned long v)
|
|
{
|
|
int l = 0;
|
|
while ((1UL << l) < v)
|
|
l++;
|
|
return l;
|
|
}
|
|
|
|
static inline void atbm_ewma_init(struct atbm_ewma *avg, unsigned long factor, unsigned long weight)
|
|
{
|
|
|
|
avg->weight = atbm_ilog2(weight);
|
|
avg->factor = atbm_ilog2(factor);
|
|
avg->internal = 0;
|
|
}
|
|
/**
|
|
* ewma_add() - Exponentially weighted moving average (EWMA)
|
|
* @avg: Average structure
|
|
* @val: Current value
|
|
*
|
|
* Add a sample to the average.
|
|
*/
|
|
static inline struct atbm_ewma *atbm_ewma_add(struct atbm_ewma *avg, unsigned long val)
|
|
{
|
|
avg->internal = avg->internal ?
|
|
(((avg->internal << avg->weight) - avg->internal) +
|
|
(val << avg->factor)) >> avg->weight :
|
|
(val << avg->factor);
|
|
return avg;
|
|
}
|
|
#define ATBM_DIV_ROUND_CLOSEST(x, divisor)( \
|
|
{ \
|
|
typeof(divisor) __divisor = divisor; \
|
|
(((x) + ((__divisor) / 2)) / (__divisor)); \
|
|
} \
|
|
)
|
|
|
|
static inline unsigned long atbm_ewma_read(const struct atbm_ewma *avg)
|
|
{
|
|
return avg->internal >> avg->factor;
|
|
}
|
|
static inline const u8 *atbm_ieee80211_find_ie(u8 eid, const u8 *ies, int len)
|
|
{
|
|
while (len > 2 && ies[0] != eid) {
|
|
len -= ies[1] + 2;
|
|
ies += ies[1] + 2;
|
|
}
|
|
if (len < 2)
|
|
return NULL;
|
|
if (len < 2 + ies[1])
|
|
return NULL;
|
|
return ies;
|
|
}
|
|
|
|
static inline const u8 *atbm_ieee80211_find_vendor_ie(unsigned int oui, u8 oui_type,
|
|
const u8 *ies, int len)
|
|
{
|
|
struct atbm_ieee80211_vendor_ie *ie;
|
|
const u8 *pos = ies, *end = ies + len;
|
|
int ie_oui;
|
|
|
|
while (pos < end) {
|
|
pos = atbm_ieee80211_find_ie(ATBM_WLAN_EID_VENDOR_SPECIFIC, pos,
|
|
end - pos);
|
|
if (!pos)
|
|
return NULL;
|
|
|
|
ie = (struct atbm_ieee80211_vendor_ie *)pos;
|
|
|
|
/* make sure we can access ie->len */
|
|
BUILD_BUG_ON(offsetof(struct atbm_ieee80211_vendor_ie, len) != 1);
|
|
|
|
if (ie->len < sizeof(*ie))
|
|
goto cont;
|
|
|
|
ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
|
|
if (ie_oui == oui && ie->oui_type == oui_type)
|
|
return pos;
|
|
cont:
|
|
pos += 2 + ie->len;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static inline u8* atbm_ieee80211_find_p2p_ie(const u8 *ie_start,size_t ie_len)
|
|
{
|
|
if((ie_start == NULL)||(ie_len == 0))
|
|
return NULL;
|
|
return (u8*)atbm_ieee80211_find_vendor_ie(ATBM_OUI_WFA,ATBM_P2P_OUI_TYPE,ie_start,ie_len);
|
|
}
|
|
|
|
static inline u8* atbm_ieee80211_find_p2p_attr(u8* attr_start,ssize_t attr_len,u8 attr_id)
|
|
{
|
|
if((attr_start == NULL)||(attr_len == 0))
|
|
return NULL;
|
|
// 3 = 1(Attribute ID) + 2(Length)
|
|
while (attr_len > 2 && attr_start[0] != attr_id) {
|
|
attr_len -= ATBM_WPA_GET_LE16((const u8*)(&attr_start[1])) + 3;
|
|
attr_start += ATBM_WPA_GET_LE16((const u8*)(&attr_start[1])) + 3;
|
|
}
|
|
|
|
if(attr_len<3)
|
|
return NULL;
|
|
if (attr_len < 3 + ATBM_WPA_GET_LE16((const u8*)(&attr_start[1])))
|
|
return NULL;
|
|
|
|
return attr_start;
|
|
}
|
|
|
|
static inline int ieee80211_p2p_action_check(u8* data,ssize_t data_len)
|
|
{
|
|
#define RETURN_ERR do{res = -1;goto action_check_end;}while(0)
|
|
int res = 0;
|
|
u8* p2p_data = data;
|
|
ssize_t p2p_data_len = data_len;
|
|
u32 oui_wfa = 0;
|
|
|
|
if(p2p_data[0] != 9/*vendor spec*/)
|
|
RETURN_ERR;
|
|
|
|
if(p2p_data_len<3)
|
|
RETURN_ERR;
|
|
|
|
p2p_data++;
|
|
p2p_data_len--;
|
|
|
|
oui_wfa = (p2p_data[0] << 16) | (p2p_data[1] << 8) | p2p_data[2];
|
|
|
|
if(oui_wfa != ATBM_OUI_WFA)
|
|
RETURN_ERR;
|
|
|
|
p2p_data += 3;
|
|
p2p_data_len -= 3;
|
|
if (p2p_data_len < 1)
|
|
RETURN_ERR;
|
|
|
|
if(p2p_data[0] != ATBM_P2P_OUI_TYPE)
|
|
RETURN_ERR;
|
|
|
|
p2p_data++;
|
|
p2p_data_len--;
|
|
|
|
if(p2p_data_len<1)
|
|
RETURN_ERR;
|
|
|
|
res = data_len-p2p_data_len;
|
|
action_check_end:
|
|
return res;
|
|
}
|
|
|
|
#ifndef do_posix_clock_monotonic_gettime
|
|
#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
|
|
#endif
|
|
static inline bool atbm_accsii_to_hex(char pos,char *res)
|
|
{
|
|
if((pos>='0')&&(pos<='9')){
|
|
*res = pos-'0';
|
|
return true;
|
|
}else if((pos>='a')&&(pos<='f')){
|
|
*res = pos - 'a'+0x0a;
|
|
return true;
|
|
}else if((pos>='A')&&(pos<='F')){
|
|
*res = pos - 'A'+0x0a;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static inline bool atbm_accsii_to_int(const char *pos,int len,int *res)
|
|
{
|
|
int res_val = 0;
|
|
int index = 0;
|
|
bool neg = false;
|
|
const char *accsii = pos;
|
|
|
|
if((len == 0) || (len>10) || (len<0))
|
|
return false;
|
|
|
|
neg = pos[0] == '-' ? true:false;
|
|
index = neg == true ? 1:0;
|
|
|
|
if((neg==true)&&(len == 1))
|
|
return false;
|
|
|
|
for(;index<len;index++){
|
|
|
|
if((accsii[index] < '0') || (accsii[index] > '9')){
|
|
return false;
|
|
}
|
|
|
|
res_val = res_val*10;
|
|
|
|
res_val += accsii[index]-'0';
|
|
}
|
|
|
|
res_val = neg == true?0-res_val:res_val;
|
|
|
|
*res = res_val;
|
|
|
|
return true;
|
|
}
|
|
static inline void atbm_common_hash_list_init(struct hlist_head *hlist,u8 size)
|
|
{
|
|
u8 index = 0;
|
|
|
|
for(index = 0;index<size;index++){
|
|
INIT_HLIST_HEAD(&hlist[index]);
|
|
}
|
|
}
|
|
|
|
static inline unsigned int atbm_hash_index(const char *string,unsigned int len,unsigned int hash_bit)
|
|
{
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
|
|
unsigned int hash = full_name_hash(NULL,string,len);
|
|
#else
|
|
unsigned int hash = full_name_hash(string,len);
|
|
#endif
|
|
|
|
return hash_32(hash, hash_bit);
|
|
}
|
|
|
|
static inline struct hlist_head *atbm_hash_list(const char *string,unsigned int len,struct hlist_head *hlist_table,unsigned int hash_bit)
|
|
{
|
|
unsigned int hash = atbm_hash_index(string,len,hash_bit);
|
|
|
|
return &hlist_table[hash];
|
|
}
|
|
static inline u8 ieee80211_rssi_weight(s8 signal)
|
|
{
|
|
u8 weight = 0;
|
|
|
|
if(signal <= -75)
|
|
weight = 0;
|
|
else if((signal>-75)&&(signal<= -65))
|
|
weight = 1;
|
|
else if((signal>-65)&&(signal<= -50))
|
|
weight = 2;
|
|
else if(signal > -50)
|
|
weight = 4;
|
|
else
|
|
weight = 0;
|
|
|
|
return weight;
|
|
}
|
|
static inline struct ieee80211_rx_status *IEEE80211_SKB_RXCB(struct sk_buff *skb)
|
|
{
|
|
return (struct ieee80211_rx_status *)skb->cb;
|
|
}
|
|
|
|
#define ATBM_SPACE ' '
|
|
#define ATBM_LINEF '\n'
|
|
#define ATBM_ENTER '\r'
|
|
#define ATBM_TAIL '\0'
|
|
#define ATBM_EQUAL '='
|
|
#define ATBM_UNUSED '#'
|
|
#define ATBM_SOH 1
|
|
#define ATBM_EOT 4
|
|
#define ATBM_STX 2
|
|
#define ATBM_ETX 3
|
|
#define ATBM_SPACE_STR " "
|
|
#define ATBM_LINEF_STR "\n"
|
|
|
|
#define ATBM_COMMON_HASHBITS 4
|
|
#define ATBM_COMMON_HASHENTRIES (1 << ATBM_COMMON_HASHBITS)
|
|
|
|
#define ATBM_MAX_SCAN_IE 1
|
|
#define ATBM_MAX_SCAN_SSID 2
|
|
#define ATBM_MAX_SCAN_MAC_FILTER 8
|
|
#define ATBM_MAX_SCAN_PRIVATE_IE_LEN (255-4)
|
|
#define ATBM_MAX_SCAN_CHANNEL (14+4)
|
|
|
|
extern u32 atbm_printk_mask;
|
|
#define ATBM_PRINTK_MASK_ERR BIT(0)
|
|
#define ATBM_PRINTK_MASK_WARN BIT(1)
|
|
#define ATBM_PRINTK_MASK_INIT BIT(2)
|
|
#define ATBM_PRINTK_MASK_EXIT BIT(3)
|
|
#define ATBM_PRINTK_MASK_BUS BIT(4)
|
|
#define ATBM_PRINTK_MASK_SCAN BIT(5)
|
|
#define ATBM_PRINTK_MASK_P2P BIT(6)
|
|
#define ATBM_PRINTK_MASK_MGMT BIT(7)
|
|
#define ATBM_PRINTK_MASK_LMAC BIT(8)
|
|
#define ATBM_PRINTK_MASK_AGG BIT(9)
|
|
#define ATBM_PRINTK_MASK_AP BIT(10)
|
|
#define ATBM_PRINTK_MASK_STA BIT(11)
|
|
#define ATBM_PRINTK_MASK_SMARTCONFIG BIT(12)
|
|
#define ATBM_PRINTK_MASK_WEXT BIT(13)
|
|
#define ATBM_PRINTK_MASK_TX BIT(14)
|
|
#define ATBM_PRINTK_MASK_RX BIT(15)
|
|
#define ATBM_PRINTK_MASK_PM BIT(16)
|
|
#define ATBM_PRINTK_MASK_PLATFROM BIT(17)
|
|
#define ATBM_PRINTK_MASK_BH BIT(18)
|
|
#define ATBM_PRINTK_MASK_CFG80211 BIT(19)
|
|
#define ATBM_PRINTK_MASK_DEBUG BIT(20)
|
|
|
|
#define ATBM_PRINTK_DEFAULT_MASK (ATBM_PRINTK_MASK_ERR|ATBM_PRINTK_MASK_WARN|ATBM_PRINTK_MASK_INIT| \
|
|
ATBM_PRINTK_MASK_EXIT|ATBM_PRINTK_MASK_SCAN|ATBM_PRINTK_MASK_LMAC|ATBM_PRINTK_MASK_PM)
|
|
#define ATBM_PRINTK_ALL ((u32)(-1))
|
|
#define ATBM_PRINTK_CLEAR (0)
|
|
#define ATBM_TAG "[atbm_log]:"
|
|
#define atbm_printk(_level,fmt,arg...) do {if(atbm_printk_mask&(_level)) printk(KERN_ERR ATBM_TAG fmt,##arg);}while(0)
|
|
|
|
#define DEBUG_PRINTF(string,args...) printk(KERN_ERR "\033[35m""[%s]:(%d) "string"\033[0m",__FUNCTION__,__LINE__,##args)
|
|
|
|
/*
|
|
*atbm printk
|
|
*/
|
|
#define atbm_printk_err(...) atbm_printk(ATBM_PRINTK_MASK_ERR,__VA_ARGS__)
|
|
#define atbm_printk_warn(...) atbm_printk(ATBM_PRINTK_MASK_WARN,__VA_ARGS__)
|
|
#define atbm_printk_init(...) atbm_printk(ATBM_PRINTK_MASK_INIT,__VA_ARGS__)
|
|
#define atbm_printk_exit(...) atbm_printk(ATBM_PRINTK_MASK_EXIT,__VA_ARGS__)
|
|
#define atbm_printk_bus(...) atbm_printk(ATBM_PRINTK_MASK_BUS,__VA_ARGS__)
|
|
#define atbm_printk_scan(...) atbm_printk(ATBM_PRINTK_MASK_SCAN,__VA_ARGS__)
|
|
#define atbm_printk_p2p(...) atbm_printk(ATBM_PRINTK_MASK_P2P,__VA_ARGS__)
|
|
#define atbm_printk_mgmt(...) atbm_printk(ATBM_PRINTK_MASK_MGMT,__VA_ARGS__)
|
|
#define atbm_printk_lmac(...) atbm_printk(ATBM_PRINTK_MASK_LMAC,__VA_ARGS__)
|
|
#define atbm_printk_agg(...) atbm_printk(ATBM_PRINTK_MASK_AGG,__VA_ARGS__)
|
|
#define atbm_printk_ap(...) atbm_printk(ATBM_PRINTK_MASK_AP,__VA_ARGS__)
|
|
#define atbm_printk_sta(...) atbm_printk(ATBM_PRINTK_MASK_STA,__VA_ARGS__)
|
|
#define atbm_printk_smt(...) atbm_printk(ATBM_PRINTK_MASK_SMARTCONFIG,__VA_ARGS__)
|
|
#define atbm_printk_wext(...) atbm_printk(ATBM_PRINTK_MASK_WEXT,__VA_ARGS__)
|
|
#define atbm_printk_tx(...) atbm_printk(ATBM_PRINTK_MASK_TX,__VA_ARGS__)
|
|
#define atbm_printk_rx(...) atbm_printk(ATBM_PRINTK_MASK_RX,__VA_ARGS__)
|
|
#define atbm_printk_pm(...) atbm_printk(ATBM_PRINTK_MASK_PM,__VA_ARGS__)
|
|
#define atbm_printk_platform(...) atbm_printk(ATBM_PRINTK_MASK_PLATFROM,__VA_ARGS__)
|
|
#define atbm_printk_bh(...) atbm_printk(ATBM_PRINTK_MASK_BH,__VA_ARGS__)
|
|
#define atbm_printk_cfg(...) atbm_printk(ATBM_PRINTK_MASK_CFG80211,__VA_ARGS__)
|
|
#define atbm_printk_debug(...) atbm_printk(ATBM_PRINTK_MASK_DEBUG,__VA_ARGS__)
|
|
#define atbm_printk_always(fmt,arg...) printk(KERN_ERR ATBM_TAG fmt,##arg)
|
|
|
|
|
|
#define ATBM_MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
|
#define ATBM_MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
|
|
static inline const char* atbm_skip_space(const char *target,ssize_t len)
|
|
{
|
|
const char* pos_end = target+len;
|
|
|
|
if((len <= 0)||(target == NULL)){
|
|
return NULL;
|
|
}
|
|
while((*target == ATBM_SPACE)||(*target == ATBM_LINEF)||(*target == ATBM_ENTER)){
|
|
target++;
|
|
if(target == pos_end){
|
|
break;
|
|
}
|
|
}
|
|
return (target == pos_end? NULL:target);
|
|
}
|
|
|
|
#define ieee80211_chw_is_ht40(chtype) (((chtype) == NL80211_CHAN_HT40PLUS) || ((chtype) == NL80211_CHAN_HT40MINUS))
|
|
#define LIGHT "\e[1m"
|
|
#define NORMAL "\e[0m"
|
|
#define ENTER "\n"
|
|
#define highlight_debug(fmt,arg...) \
|
|
printk(KERN_ERR LIGHT fmt NORMAL ENTER,##arg)
|
|
|
|
#ifdef MODULE
|
|
#define atbm_module_parent (&THIS_MODULE->mkobj.kobj)
|
|
#else
|
|
#define atbm_module_parent (NULL)
|
|
#endif
|
|
/*
|
|
*atbm timer function
|
|
*/
|
|
struct atbm_timer_list {
|
|
struct timer_list timer;
|
|
void (*function)(unsigned long data);
|
|
unsigned long data;
|
|
unsigned long expires;
|
|
};
|
|
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
|
|
static inline void atbm_timer_handle(struct timer_list *in_timer)
|
|
#else
|
|
static inline void atbm_timer_handle(unsigned long data)
|
|
#endif
|
|
{
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
|
|
struct atbm_timer_list *atbm_timer = from_timer(atbm_timer, in_timer, timer);
|
|
#else
|
|
struct atbm_timer_list *atbm_timer = (struct atbm_timer_list *)data;
|
|
#endif
|
|
BUG_ON(atbm_timer->function == NULL);
|
|
atbm_timer->function(atbm_timer->data);
|
|
}
|
|
|
|
static inline void atbm_init_timer(struct atbm_timer_list *atbm_timer)
|
|
{
|
|
atbm_timer->expires = 0;
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
|
|
timer_setup(&atbm_timer->timer, atbm_timer_handle, 0);
|
|
#else
|
|
/* setup_timer(ptimer, pfunc,(u32)cntx); */
|
|
atbm_timer->timer.function = atbm_timer_handle;
|
|
atbm_timer->timer.data = (unsigned long)atbm_timer;
|
|
init_timer(&atbm_timer->timer);
|
|
#endif
|
|
}
|
|
|
|
static inline void atbm_setup_timer(struct atbm_timer_list *atbm_timer,
|
|
void (*function)(unsigned long data),unsigned long data)
|
|
{
|
|
atbm_timer->expires = 0;
|
|
atbm_timer->function = function;
|
|
atbm_timer->data = data;
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
|
|
timer_setup(&atbm_timer->timer, atbm_timer_handle, 0);
|
|
#else
|
|
|
|
atbm_timer->timer.function = atbm_timer_handle;
|
|
atbm_timer->timer.data = (unsigned long)atbm_timer;
|
|
init_timer(&atbm_timer->timer);
|
|
#endif
|
|
}
|
|
static inline int atbm_del_timer_sync(struct atbm_timer_list *atbm_timer)
|
|
{
|
|
return del_timer_sync(&atbm_timer->timer);
|
|
}
|
|
static inline int atbm_mod_timer(struct atbm_timer_list *atbm_timer, unsigned long expires)
|
|
{
|
|
int ret = 0;
|
|
ret = mod_timer(&atbm_timer->timer,expires);
|
|
atbm_timer->expires = atbm_timer->timer.expires;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline void atbm_add_timer(struct atbm_timer_list *atbm_timer)
|
|
{
|
|
add_timer(&atbm_timer->timer);
|
|
}
|
|
|
|
static inline int atbm_del_timer(struct atbm_timer_list *atbm_timer)
|
|
{
|
|
return del_timer(&atbm_timer->timer);
|
|
}
|
|
static inline int atbm_timer_pending(struct atbm_timer_list *atbm_timer)
|
|
{
|
|
return timer_pending(&atbm_timer->timer);
|
|
}
|
|
|
|
#endif /* MAC80211_H */
|