staging: rtl8192u: Remove broken driver

Tests on rtl8192u hardware have shown that this driver is broken since
2016. Remove broken driver. Find fix for two bugs in second link.

Link: https://lore.kernel.org/lkml/db98d9ac-7650-4a72-8eb9-4def1f17ea0d@app.fastmail.com/
Link: https://lore.kernel.org/lkml/cover.1697089416.git.philipp.g.hortmann@gmail.com/
Signed-off-by: Philipp Hortmann <philipp.g.hortmann@gmail.com>
Link: https://lore.kernel.org/r/20231014211051.GA29518@matrix-ESPRIMO-P710
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Philipp Hortmann 2023-10-14 23:10:51 +02:00 committed by Greg Kroah-Hartman
parent a7e79e2b6f
commit 697455ce41
48 changed files with 0 additions and 29816 deletions

View File

@ -28,8 +28,6 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/olpc_dcon/Kconfig"
source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"
source "drivers/staging/rtl8723bs/Kconfig"

View File

@ -1,12 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config RTL8192U
tristate "RealTek RTL8192U Wireless LAN NIC driver"
depends on PCI && WLAN && USB
depends on m
select WIRELESS_EXT
select WEXT_PRIV
select CRC32
select CRYPTO
select CRYPTO_AES
select CRYPTO_CCM
select CRYPTO_LIB_ARC4

View File

@ -1,27 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
NIC_SELECT = RTL8192U
ccflags-y += -DCONFIG_FORCE_HARD_FLOAT=y
ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
ccflags-y += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO
r8192u_usb-y := r8192U_core.o r8180_93cx6.o r8192U_wx.o \
r8190_rtl8256.o r819xU_phy.o r819xU_firmware.o \
r819xU_cmdpkt.o r8192U_dm.o r819xU_firmware_img.o \
r8192U_debugfs.o \
ieee80211/ieee80211_crypt.o \
ieee80211/ieee80211_crypt_tkip.o \
ieee80211/ieee80211_crypt_ccmp.o \
ieee80211/ieee80211_crypt_wep.o \
ieee80211/ieee80211_rx.o \
ieee80211/ieee80211_softmac.o \
ieee80211/ieee80211_tx.o \
ieee80211/ieee80211_wx.o \
ieee80211/ieee80211_module.o \
ieee80211/ieee80211_softmac_wx.o \
ieee80211/rtl819x_HTProc.o \
ieee80211/rtl819x_TSProc.o \
ieee80211/rtl819x_BAProc.o \
ieee80211/dot11d.o
obj-$(CONFIG_RTL8192U) += r8192u_usb.o

View File

@ -1,16 +0,0 @@
To-do list:
* Correct the coding style according to Linux guidelines; please read the document
at https://www.kernel.org/doc/html/latest/process/coding-style.html.
* Remove unnecessary debugging/printing macros; for those that are still needed
use the proper kernel API (pr_debug(), dev_dbg(), netdev_dbg()).
* Remove dead code such as unusued functions, variables, fields, etc..
* Use in-kernel API and remove unnecessary wrappers where possible.
* Fix bugs due to code that sleeps in atomic context.
* Remove the HAL layer and migrate its functionality into the relevant parts of
the driver.
* Switch to use LIB80211.
* Switch to use MAC80211.
* Switch to use CFG80211.
* Improve the error handling of various functions, particularly those that use
existing kernel APIs.

View File

@ -1 +0,0 @@
Andrea Merello <andrea.merello@gmail.com>

View File

@ -1,4 +0,0 @@
v 0.1
First version.
This is based on the rtl8180-sa2400 pre-0.22-CVS code..

View File

@ -1,174 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/* Implement 802.11d. */
#include "dot11d.h"
void rtl8192u_dot11d_init(struct ieee80211_device *ieee)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
dot11d_info->dot11d_enabled = false;
dot11d_info->state = DOT11D_STATE_NONE;
dot11d_info->country_ie_len = 0;
memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
RESET_CIE_WATCHDOG(ieee);
}
EXPORT_SYMBOL(rtl8192u_dot11d_init);
/* Reset to the state as we are just entering a regulatory domain. */
void dot11d_reset(struct ieee80211_device *ieee)
{
u32 i;
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
/* Clear old channel map */
memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
/* Set new channel map */
for (i = 1; i <= 11; i++)
(dot11d_info->channel_map)[i] = 1;
for (i = 12; i <= 14; i++)
(dot11d_info->channel_map)[i] = 2;
dot11d_info->state = DOT11D_STATE_NONE;
dot11d_info->country_ie_len = 0;
RESET_CIE_WATCHDOG(ieee);
}
EXPORT_SYMBOL(dot11d_reset);
/*
* Update country IE from Beacon or Probe Resopnse and configure PHY for
* operation in the regulatory domain.
*
* TODO: Configure Tx power.
* Assumption:
* 1. IS_DOT11D_ENABLE() is TRUE.
* 2. Input IE is an valid one.
*/
void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr,
u16 CoutryIeLen, u8 *pCoutryIe)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
u8 i, j, NumTriples, MaxChnlNum;
struct chnl_txpower_triple *pTriple;
memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
MaxChnlNum = 0;
NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3);
for (i = 0; i < NumTriples; i++) {
if (MaxChnlNum >= pTriple->first_channel) {
/* It is not in a monotonically increasing order, so
* stop processing.
*/
netdev_err(dev->dev, "%s: Invalid country IE, skip it 1\n", __func__);
return;
}
if (MAX_CHANNEL_NUMBER < (pTriple->first_channel + pTriple->num_channels)) {
/* It is not a valid set of channel id, so stop
* processing.
*/
netdev_err(dev->dev, "%s: Invalid country IE, skip it 2\n", __func__);
return;
}
for (j = 0; j < pTriple->num_channels; j++) {
dot11d_info->channel_map[pTriple->first_channel + j] = 1;
dot11d_info->max_tx_pwr_dbm_list[pTriple->first_channel + j] = pTriple->max_tx_pwr_dbm;
MaxChnlNum = pTriple->first_channel + j;
}
pTriple = (struct chnl_txpower_triple *)((u8 *)pTriple + 3);
}
netdev_info(dev->dev, "Channel List:");
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
if (dot11d_info->channel_map[i] > 0)
netdev_info(dev->dev, " %d", i);
netdev_info(dev->dev, "\n");
UPDATE_CIE_SRC(dev, pTaddr);
dot11d_info->country_ie_len = CoutryIeLen;
memcpy(dot11d_info->country_ie_buf, pCoutryIe, CoutryIeLen);
dot11d_info->state = DOT11D_STATE_LEARNED;
}
EXPORT_SYMBOL(dot11d_update_country_ie);
u8 dot11d_get_max_tx_pwr_in_dbm(struct ieee80211_device *dev, u8 Channel)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
u8 MaxTxPwrInDbm = 255;
if (Channel > MAX_CHANNEL_NUMBER) {
netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
return MaxTxPwrInDbm;
}
if (dot11d_info->channel_map[Channel])
MaxTxPwrInDbm = dot11d_info->max_tx_pwr_dbm_list[Channel];
return MaxTxPwrInDbm;
}
EXPORT_SYMBOL(dot11d_get_max_tx_pwr_in_dbm);
void dot11d_scan_complete(struct ieee80211_device *dev)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
switch (dot11d_info->state) {
case DOT11D_STATE_LEARNED:
dot11d_info->state = DOT11D_STATE_DONE;
break;
case DOT11D_STATE_DONE:
if (GET_CIE_WATCHDOG(dev) == 0) {
/* Reset country IE if previous one is gone. */
dot11d_reset(dev);
}
break;
case DOT11D_STATE_NONE:
break;
}
}
EXPORT_SYMBOL(dot11d_scan_complete);
int is_legal_channel(struct ieee80211_device *dev, u8 channel)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
if (channel > MAX_CHANNEL_NUMBER) {
netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
return 0;
}
if (dot11d_info->channel_map[channel] > 0)
return 1;
return 0;
}
EXPORT_SYMBOL(is_legal_channel);
int to_legal_channel(struct ieee80211_device *dev, u8 channel)
{
struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
u8 default_chn = 0;
u32 i = 0;
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
if (dot11d_info->channel_map[i] > 0) {
default_chn = i;
break;
}
}
if (channel > MAX_CHANNEL_NUMBER) {
netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
return default_chn;
}
if (dot11d_info->channel_map[channel] > 0)
return channel;
return default_chn;
}
EXPORT_SYMBOL(to_legal_channel);

View File

@ -1,57 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __INC_DOT11D_H
#define __INC_DOT11D_H
#include "ieee80211.h"
struct chnl_txpower_triple {
u8 first_channel;
u8 num_channels;
u8 max_tx_pwr_dbm;
};
enum dot11d_state {
DOT11D_STATE_NONE = 0,
DOT11D_STATE_LEARNED,
DOT11D_STATE_DONE,
};
struct rt_dot11d_info {
u16 country_ie_len; /* > 0 if country_ie_buf[] contains valid country information element. */
/* country_ie_src_addr u16 aligned for comparison and copy */
u8 country_ie_src_addr[ETH_ALEN]; /* Source AP of the country IE. */
u8 country_ie_buf[MAX_IE_LEN];
u8 country_ie_watchdog;
u8 channel_map[MAX_CHANNEL_NUMBER + 1]; /* !Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
u8 max_tx_pwr_dbm_list[MAX_CHANNEL_NUMBER + 1];
enum dot11d_state state;
u8 dot11d_enabled; /* dot11MultiDomainCapabilityEnabled */
};
#define GET_DOT11D_INFO(ieee_dev) ((struct rt_dot11d_info *)((ieee_dev)->dot11d_info))
#define IS_DOT11D_ENABLE(ieee_dev) (GET_DOT11D_INFO(ieee_dev)->dot11d_enabled)
#define IS_COUNTRY_IE_VALID(ieee_dev) (GET_DOT11D_INFO(ieee_dev)->country_ie_len > 0)
#define IS_EQUAL_CIE_SRC(ieee_dev, addr) ether_addr_equal(GET_DOT11D_INFO(ieee_dev)->country_ie_src_addr, addr)
#define UPDATE_CIE_SRC(ieee_dev, addr) ether_addr_copy(GET_DOT11D_INFO(ieee_dev)->country_ie_src_addr, addr)
#define GET_CIE_WATCHDOG(ieee_dev) (GET_DOT11D_INFO(ieee_dev)->country_ie_watchdog)
#define RESET_CIE_WATCHDOG(ieee_dev) (GET_CIE_WATCHDOG(ieee_dev) = 0)
#define UPDATE_CIE_WATCHDOG(ieee_dev) (++GET_CIE_WATCHDOG(ieee_dev))
void rtl8192u_dot11d_init(struct ieee80211_device *dev);
void dot11d_reset(struct ieee80211_device *dev);
void dot11d_update_country_ie(struct ieee80211_device *dev,
u8 *addr,
u16 coutry_ie_len,
u8 *coutry_ie);
u8 dot11d_get_max_tx_pwr_in_dbm(struct ieee80211_device *dev, u8 channel);
void dot11d_scan_complete(struct ieee80211_device *dev);
int is_legal_channel(struct ieee80211_device *dev, u8 channel);
int to_legal_channel(struct ieee80211_device *dev, u8 channel);
#endif /* #ifndef __INC_DOT11D_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,235 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Host AP crypto routines
*
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include "ieee80211.h"
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("HostAP crypto");
MODULE_LICENSE("GPL");
struct ieee80211_crypto_alg {
struct list_head list;
struct ieee80211_crypto_ops *ops;
};
struct ieee80211_crypto {
struct list_head algs;
spinlock_t lock;
};
static struct ieee80211_crypto *hcrypt;
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
int force)
{
struct list_head *ptr, *n;
struct ieee80211_crypt_data *entry;
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
entry = list_entry(ptr, struct ieee80211_crypt_data, list);
if (atomic_read(&entry->refcnt) != 0 && !force)
continue;
list_del(ptr);
if (entry->ops)
entry->ops->deinit(entry->priv);
kfree(entry);
}
}
void ieee80211_crypt_deinit_handler(struct timer_list *t)
{
struct ieee80211_device *ieee = from_timer(ieee, t, crypt_deinit_timer);
unsigned long flags;
spin_lock_irqsave(&ieee->lock, flags);
ieee80211_crypt_deinit_entries(ieee, 0);
if (!list_empty(&ieee->crypt_deinit_list)) {
netdev_dbg(ieee->dev, "%s: entries remaining in delayed crypt deletion list\n",
ieee->dev->name);
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt)
{
struct ieee80211_crypt_data *tmp;
unsigned long flags;
if (!(*crypt))
return;
tmp = *crypt;
*crypt = NULL;
/* must not run ops->deinit() while there may be pending encrypt or
* decrypt operations. Use a list of delayed deinits to avoid needing
* locking.
*/
spin_lock_irqsave(&ieee->lock, flags);
list_add(&tmp->list, &ieee->crypt_deinit_list);
if (!timer_pending(&ieee->crypt_deinit_timer)) {
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct ieee80211_crypto_alg *alg;
if (!hcrypt)
return -1;
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (!alg)
return -ENOMEM;
alg->ops = ops;
spin_lock_irqsave(&hcrypt->lock, flags);
list_add(&alg->list, &hcrypt->algs);
spin_unlock_irqrestore(&hcrypt->lock, flags);
pr_debug("ieee80211_crypt: registered algorithm '%s'\n",
ops->name);
return 0;
}
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *del_alg = NULL;
if (!hcrypt)
return -1;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *)ptr;
if (alg->ops == ops) {
list_del(&alg->list);
del_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (del_alg) {
pr_debug("ieee80211_crypt: unregistered algorithm '%s'\n",
ops->name);
kfree(del_alg);
}
return del_alg ? 0 : -1;
}
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *found_alg = NULL;
if (!hcrypt)
return NULL;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *)ptr;
if (strcmp(alg->ops->name, name) == 0) {
found_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (found_alg)
return found_alg->ops;
return NULL;
}
static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; }
static void ieee80211_crypt_null_deinit(void *priv) {}
static struct ieee80211_crypto_ops ieee80211_crypt_null = {
.name = "NULL",
.init = ieee80211_crypt_null_init,
.deinit = ieee80211_crypt_null_deinit,
.encrypt_mpdu = NULL,
.decrypt_mpdu = NULL,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = NULL,
.get_key = NULL,
.extra_prefix_len = 0,
.extra_postfix_len = 0,
.owner = THIS_MODULE,
};
int __init ieee80211_crypto_init(void)
{
int ret = -ENOMEM;
hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
if (!hcrypt)
goto out;
INIT_LIST_HEAD(&hcrypt->algs);
spin_lock_init(&hcrypt->lock);
ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
if (ret < 0) {
kfree(hcrypt);
hcrypt = NULL;
}
out:
return ret;
}
void ieee80211_crypto_deinit(void)
{
struct list_head *ptr, *n;
if (!hcrypt)
return;
for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
ptr = n, n = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *)ptr;
list_del(ptr);
pr_debug("ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
alg->ops->name);
kfree(alg);
}
kfree(hcrypt);
}

View File

@ -1,86 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Original code based on Host AP (software wireless LAN access point) driver
* for Intersil Prism2/2.5/3.
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
* <jketreno@linux.intel.com>
*
* Copyright (c) 2004, Intel Corporation
*/
/*
* This file defines the interface to the ieee80211 crypto module.
*/
#ifndef IEEE80211_CRYPT_H
#define IEEE80211_CRYPT_H
#include <linux/skbuff.h>
struct ieee80211_crypto_ops {
const char *name;
/* init new crypto context (e.g., allocate private data space,
* select IV, etc.); returns NULL on failure or pointer to allocated
* private data on success
*/
void * (*init)(int keyidx);
/* deinitialize crypto context and free allocated private data */
void (*deinit)(void *priv);
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the
* encryption; if not, error will be returned; these functions are
* called for all MPDUs (i.e., fragments).
*/
int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
/* These functions are called for full MSDUs, i.e. full frames.
* These can be NULL if full MSDU operations are not needed.
*/
int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
void *priv);
int (*set_key)(void *key, int len, u8 *seq, void *priv);
int (*get_key)(void *key, int len, u8 *seq, void *priv);
/* procfs handler for printing out key information and possible
* statistics
*/
char * (*print_stats)(char *p, void *priv);
/* maximum number of bytes added by encryption; encrypt buf is
* allocated with extra_prefix_len bytes, copy of in_buf, and
* extra_postfix_len; encrypt need not use all this space, but
* the result must start at the beginning of the buffer and correct
* length must be returned
*/
int extra_prefix_len, extra_postfix_len;
struct module *owner;
};
struct ieee80211_crypt_data {
struct list_head list; /* delayed deletion list */
struct ieee80211_crypto_ops *ops;
void *priv;
atomic_t refcnt;
};
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force);
void ieee80211_crypt_deinit_handler(struct timer_list *t);
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt);
#endif

View File

@ -1,421 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Host AP crypt: host-based CCMP encryption implementation for Host AP driver
*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/string.h>
#include <linux/wireless.h>
#include "ieee80211.h"
#include <linux/crypto.h>
#include <crypto/aead.h>
#include <linux/scatterlist.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: CCMP");
MODULE_LICENSE("GPL");
#define AES_BLOCK_LEN 16
#define CCMP_HDR_LEN 8
#define CCMP_MIC_LEN 8
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
struct ieee80211_ccmp_data {
u8 key[CCMP_TK_LEN];
int key_set;
u8 tx_pn[CCMP_PN_LEN];
u8 rx_pn[CCMP_PN_LEN];
u32 dot11RSNAStatsCCMPFormatErrors;
u32 dot11RSNAStatsCCMPReplays;
u32 dot11RSNAStatsCCMPDecryptErrors;
int key_idx;
struct crypto_aead *tfm;
/* scratch buffers for virt_to_page() (crypto API) */
u8 tx_aad[2 * AES_BLOCK_LEN];
u8 rx_aad[2 * AES_BLOCK_LEN];
};
static void *ieee80211_ccmp_init(int key_idx)
{
struct ieee80211_ccmp_data *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
goto fail;
priv->key_idx = key_idx;
priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tfm)) {
pr_debug("ieee80211_crypt_ccmp: could not allocate crypto API aes\n");
priv->tfm = NULL;
goto fail;
}
return priv;
fail:
if (priv) {
if (priv->tfm)
crypto_free_aead(priv->tfm);
kfree(priv);
}
return NULL;
}
static void ieee80211_ccmp_deinit(void *priv)
{
struct ieee80211_ccmp_data *_priv = priv;
if (_priv && _priv->tfm)
crypto_free_aead(_priv->tfm);
kfree(priv);
}
static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr,
u8 *pn, u8 *iv, u8 *aad)
{
u8 *pos, qc = 0;
size_t aad_len;
u16 fc;
int a4_included, qc_included;
fc = le16_to_cpu(hdr->frame_ctl);
a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
/* qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
* (WLAN_FC_GET_STYPE(fc) & 0x08));
*/
/* fixed by David :2006.9.6 */
qc_included = (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
(WLAN_FC_GET_STYPE(fc) & 0x80);
aad_len = 22;
if (a4_included)
aad_len += 6;
if (qc_included) {
pos = (u8 *)&hdr->addr4;
if (a4_included)
pos += 6;
qc = *pos & 0x0f;
aad_len += 2;
}
/* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
* mode authentication are not allowed to collide, yet both are derived
* from the same vector. We only set L := 1 here to indicate that the
* data size can be represented in (L+1) bytes. The CCM layer will take
* care of storing the data length in the top (L+1) bytes and setting
* and clearing the other bits as is required to derive the two IVs.
*/
iv[0] = 0x1;
/* Nonce: QC | A2 | PN */
iv[1] = qc;
memcpy(iv + 2, hdr->addr2, ETH_ALEN);
memcpy(iv + 8, pn, CCMP_PN_LEN);
/* AAD:
* FC with bits 4..6 and 11..13 masked to zero; 14 is always one
* A1 | A2 | A3
* SC with bits 4..15 (seq#) masked to zero
* A4 (if present)
* QC (if present)
*/
pos = (u8 *)hdr;
aad[0] = pos[0] & 0x8f;
aad[1] = pos[1] & 0xc7;
memcpy(&aad[2], &hdr->addr1, ETH_ALEN);
memcpy(&aad[8], &hdr->addr2, ETH_ALEN);
memcpy(&aad[14], &hdr->addr3, ETH_ALEN);
pos = (u8 *)&hdr->seq_ctl;
aad[20] = pos[0] & 0x0f;
aad[21] = 0; /* all bits masked */
memset(aad + 22, 0, 8);
if (a4_included)
memcpy(aad + 22, hdr->addr4, ETH_ALEN);
if (qc_included) {
aad[a4_included ? 28 : 22] = qc;
/* rest of QC masked */
}
return aad_len;
}
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
int i;
u8 *pos;
struct rtl_80211_hdr_4addr *hdr;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
if (skb_headroom(skb) < CCMP_HDR_LEN ||
skb_tailroom(skb) < CCMP_MIC_LEN ||
skb->len < hdr_len)
return -1;
pos = skb_push(skb, CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
pos += hdr_len;
/* mic = skb_put(skb, CCMP_MIC_LEN); */
i = CCMP_PN_LEN - 1;
while (i >= 0) {
key->tx_pn[i]++;
if (key->tx_pn[i] != 0)
break;
i--;
}
*pos++ = key->tx_pn[5];
*pos++ = key->tx_pn[4];
*pos++ = 0;
*pos++ = (key->key_idx << 6) | BIT(5) /* Ext IV included */;
*pos++ = key->tx_pn[3];
*pos++ = key->tx_pn[2];
*pos++ = key->tx_pn[1];
*pos++ = key->tx_pn[0];
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
if (!tcb_desc->bHwSec) {
struct aead_request *req;
struct scatterlist sg[2];
u8 *aad = key->tx_aad;
u8 iv[AES_BLOCK_LEN];
int aad_len, ret;
size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN;
req = aead_request_alloc(key->tfm, GFP_ATOMIC);
if (!req)
return -ENOMEM;
aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad);
skb_put(skb, CCMP_MIC_LEN);
sg_init_table(sg, 2);
sg_set_buf(&sg[0], aad, aad_len);
sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN,
data_len + CCMP_MIC_LEN);
aead_request_set_callback(req, 0, NULL, NULL);
aead_request_set_ad(req, aad_len);
aead_request_set_crypt(req, sg, sg, data_len, iv);
ret = crypto_aead_encrypt(req);
aead_request_free(req);
return ret;
}
return 0;
}
static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
u8 keyidx, *pos;
struct rtl_80211_hdr_4addr *hdr;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 pn[6];
if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
key->dot11RSNAStatsCCMPFormatErrors++;
return -1;
}
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & BIT(5))) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "CCMP: received packet without ExtIV flag from %pM\n",
hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
}
keyidx >>= 6;
if (key->key_idx != keyidx) {
netdev_dbg(skb->dev, "CCMP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
key->key_idx, keyidx, priv);
return -6;
}
if (!key->key_set) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "CCMP: received packet from %pM with keyid=%d that does not have a configured key\n",
hdr->addr2, keyidx);
}
return -3;
}
pn[0] = pos[7];
pn[1] = pos[6];
pn[2] = pos[5];
pn[3] = pos[4];
pn[4] = pos[1];
pn[5] = pos[0];
pos += 8;
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "CCMP: replay detected: STA=%pM previous PN %pm received PN %pm\n",
hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
}
if (!tcb_desc->bHwSec) {
struct aead_request *req;
struct scatterlist sg[2];
u8 *aad = key->rx_aad;
u8 iv[AES_BLOCK_LEN];
int aad_len, ret;
size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN;
req = aead_request_alloc(key->tfm, GFP_ATOMIC);
if (!req)
return -ENOMEM;
aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad);
sg_init_table(sg, 2);
sg_set_buf(&sg[0], aad, aad_len);
sg_set_buf(&sg[1], pos, data_len);
aead_request_set_callback(req, 0, NULL, NULL);
aead_request_set_ad(req, aad_len);
aead_request_set_crypt(req, sg, sg, data_len, iv);
ret = crypto_aead_decrypt(req);
aead_request_free(req);
if (ret) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "CCMP: decrypt failed: STA=%pM\n",
hdr->addr2);
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
}
memcpy(key->rx_pn, pn, CCMP_PN_LEN);
}
/* Remove hdr and MIC */
memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
skb_pull(skb, CCMP_HDR_LEN);
skb_trim(skb, skb->len - CCMP_MIC_LEN);
return keyidx;
}
static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
int keyidx;
struct crypto_aead *tfm = data->tfm;
keyidx = data->key_idx;
memset(data, 0, sizeof(*data));
data->key_idx = keyidx;
if (len == CCMP_TK_LEN) {
memcpy(data->key, key, CCMP_TK_LEN);
data->key_set = 1;
if (seq) {
data->rx_pn[0] = seq[5];
data->rx_pn[1] = seq[4];
data->rx_pn[2] = seq[3];
data->rx_pn[3] = seq[2];
data->rx_pn[4] = seq[1];
data->rx_pn[5] = seq[0];
}
if (crypto_aead_setauthsize(tfm, CCMP_MIC_LEN) ||
crypto_aead_setkey(tfm, data->key, CCMP_TK_LEN))
return -1;
} else if (len == 0) {
data->key_set = 0;
} else {
return -1;
}
return 0;
}
static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
if (len < CCMP_TK_LEN)
return 0;
if (!data->key_set)
return 0;
memcpy(key, data->key, CCMP_TK_LEN);
if (seq) {
seq[0] = data->tx_pn[5];
seq[1] = data->tx_pn[4];
seq[2] = data->tx_pn[3];
seq[3] = data->tx_pn[2];
seq[4] = data->tx_pn[1];
seq[5] = data->tx_pn[0];
}
return CCMP_TK_LEN;
}
static char *ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p, "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
ccmp->tx_pn, ccmp->rx_pn,
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
.name = "CCMP",
.init = ieee80211_ccmp_init,
.deinit = ieee80211_ccmp_deinit,
.encrypt_mpdu = ieee80211_ccmp_encrypt,
.decrypt_mpdu = ieee80211_ccmp_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = ieee80211_ccmp_set_key,
.get_key = ieee80211_ccmp_get_key,
.print_stats = ieee80211_ccmp_print_stats,
.extra_prefix_len = CCMP_HDR_LEN,
.extra_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};
int __init ieee80211_crypto_ccmp_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
}
void ieee80211_crypto_ccmp_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
}

View File

@ -1,718 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Host AP crypt: host-based TKIP encryption implementation for Host AP driver
*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*/
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/string.h>
#include "ieee80211.h"
#include <crypto/arc4.h>
#include <crypto/hash.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: TKIP");
MODULE_LICENSE("GPL");
struct ieee80211_tkip_data {
#define TKIP_KEY_LEN 32
u8 key[TKIP_KEY_LEN];
int key_set;
u32 tx_iv32;
u16 tx_iv16;
u16 tx_ttak[5];
int tx_phase1_done;
u32 rx_iv32;
u16 rx_iv16;
u16 rx_ttak[5];
int rx_phase1_done;
u32 rx_iv32_new;
u16 rx_iv16_new;
u32 dot11RSNAStatsTKIPReplays;
u32 dot11RSNAStatsTKIPICVErrors;
u32 dot11RSNAStatsTKIPLocalMICFailures;
int key_idx;
struct arc4_ctx rx_ctx_arc4;
struct arc4_ctx tx_ctx_arc4;
struct crypto_shash *rx_tfm_michael;
struct crypto_shash *tx_tfm_michael;
/* scratch buffers for virt_to_page() (crypto API) */
u8 rx_hdr[16], tx_hdr[16];
};
static void *ieee80211_tkip_init(int key_idx)
{
struct ieee80211_tkip_data *priv;
if (fips_enabled)
return NULL;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
goto fail;
priv->key_idx = key_idx;
priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->tx_tfm_michael)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API michael_mic\n");
priv->tx_tfm_michael = NULL;
goto fail;
}
priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->rx_tfm_michael)) {
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
"crypto API michael_mic\n");
priv->rx_tfm_michael = NULL;
goto fail;
}
return priv;
fail:
if (priv) {
crypto_free_shash(priv->tx_tfm_michael);
crypto_free_shash(priv->rx_tfm_michael);
kfree(priv);
}
return NULL;
}
static void ieee80211_tkip_deinit(void *priv)
{
struct ieee80211_tkip_data *_priv = priv;
if (_priv) {
crypto_free_shash(_priv->tx_tfm_michael);
crypto_free_shash(_priv->rx_tfm_michael);
}
kfree_sensitive(priv);
}
static inline u16 RotR1(u16 val)
{
return (val >> 1) | (val << 15);
}
static inline u8 Lo8(u16 val)
{
return val & 0xff;
}
static inline u8 Hi8(u16 val)
{
return val >> 8;
}
static inline u16 Lo16(u32 val)
{
return val & 0xffff;
}
static inline u16 Hi16(u32 val)
{
return val >> 16;
}
static inline u16 Mk16(u8 hi, u8 lo)
{
return lo | (((u16)hi) << 8);
}
static const u16 Sbox[256] = {
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
};
static inline u16 _S_(u16 v)
{
u16 t = Sbox[Hi8(v)];
return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
}
#define PHASE1_LOOP_COUNT 8
static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
{
int i, j;
/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
TTAK[0] = Lo16(IV32);
TTAK[1] = Hi16(IV32);
TTAK[2] = Mk16(TA[1], TA[0]);
TTAK[3] = Mk16(TA[3], TA[2]);
TTAK[4] = Mk16(TA[5], TA[4]);
for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
j = 2 * (i & 1);
TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
}
}
static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
u16 IV16)
{
/*
* Make temporary area overlap WEP seed so that the final copy can be
* avoided on little endian hosts.
*/
u16 *PPK = (u16 *)&WEPSeed[4];
/* Step 1 - make copy of TTAK and bring in TSC */
PPK[0] = TTAK[0];
PPK[1] = TTAK[1];
PPK[2] = TTAK[2];
PPK[3] = TTAK[3];
PPK[4] = TTAK[4];
PPK[5] = TTAK[4] + IV16;
/* Step 2 - 96-bit bijective mixing using S-box */
PPK[0] += _S_(PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[0])));
PPK[1] += _S_(PPK[0] ^ le16_to_cpu(*(__le16 *)(&TK[2])));
PPK[2] += _S_(PPK[1] ^ le16_to_cpu(*(__le16 *)(&TK[4])));
PPK[3] += _S_(PPK[2] ^ le16_to_cpu(*(__le16 *)(&TK[6])));
PPK[4] += _S_(PPK[3] ^ le16_to_cpu(*(__le16 *)(&TK[8])));
PPK[5] += _S_(PPK[4] ^ le16_to_cpu(*(__le16 *)(&TK[10])));
PPK[0] += RotR1(PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[12])));
PPK[1] += RotR1(PPK[0] ^ le16_to_cpu(*(__le16 *)(&TK[14])));
PPK[2] += RotR1(PPK[1]);
PPK[3] += RotR1(PPK[2]);
PPK[4] += RotR1(PPK[3]);
PPK[5] += RotR1(PPK[4]);
/*
* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
* WEPSeed[0..2] is transmitted as WEP IV
*/
WEPSeed[0] = Hi8(IV16);
WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
WEPSeed[2] = Lo8(IV16);
WEPSeed[3] = Lo8((PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[0]))) >> 1);
#ifdef __BIG_ENDIAN
{
int i;
for (i = 0; i < 6; i++)
PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
}
#endif
}
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
int len;
u8 *pos;
struct rtl_80211_hdr_4addr *hdr;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 rc4key[16], *icv;
u32 crc;
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
if (!tcb_desc->bHwSec) {
if (!tkey->tx_phase1_done) {
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
tkey->tx_iv32);
tkey->tx_phase1_done = 1;
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
} else
tkey->tx_phase1_done = 1;
len = skb->len - hdr_len;
pos = skb_push(skb, 8);
memmove(pos, pos + 8, hdr_len);
pos += hdr_len;
if (tcb_desc->bHwSec) {
*pos++ = Hi8(tkey->tx_iv16);
*pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
*pos++ = Lo8(tkey->tx_iv16);
} else {
*pos++ = rc4key[0];
*pos++ = rc4key[1];
*pos++ = rc4key[2];
}
*pos++ = (tkey->key_idx << 6) | BIT(5) /* Ext IV included */;
*pos++ = tkey->tx_iv32 & 0xff;
*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
if (!tcb_desc->bHwSec) {
icv = skb_put(skb, 4);
crc = ~crc32_le(~0, pos, len);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16);
arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4);
}
tkey->tx_iv16++;
if (tkey->tx_iv16 == 0) {
tkey->tx_phase1_done = 0;
tkey->tx_iv32++;
}
return 0;
}
static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 keyidx, *pos;
u32 iv32;
u16 iv16;
struct rtl_80211_hdr_4addr *hdr;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 rc4key[16];
u8 icv[4];
u32 crc;
int plen;
if (skb->len < hdr_len + 8 + 4)
return -1;
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & BIT(5))) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "TKIP: received packet without ExtIV"
" flag from %pM\n", hdr->addr2);
}
return -2;
}
keyidx >>= 6;
if (tkey->key_idx != keyidx) {
netdev_dbg(skb->dev, "TKIP: RX tkey->key_idx=%d frame "
"keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
return -6;
}
if (!tkey->key_set) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
" key\n", hdr->addr2, keyidx);
}
return -3;
}
iv16 = (pos[0] << 8) | pos[2];
iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
pos += 8;
if (!tcb_desc->bHwSec) {
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
netdev_dbg(skb->dev, "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
"%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
return -4;
}
if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
tkey->rx_phase1_done = 1;
}
tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
plen = skb->len - hdr_len - 12;
arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16);
arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4);
crc = ~crc32_le(~0, pos, plen);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
if (memcmp(icv, pos + plen, 4) != 0) {
if (iv32 != tkey->rx_iv32) {
/*
* Previously cached Phase1 result was already
* lost, so it needs to be recalculated for the
* next packet.
*/
tkey->rx_phase1_done = 0;
}
if (net_ratelimit()) {
netdev_dbg(skb->dev, "TKIP: ICV error detected: STA="
"%pM\n", hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
}
}
/*
* Update real counters only after Michael MIC verification has
* completed.
*/
tkey->rx_iv32_new = iv32;
tkey->rx_iv16_new = iv16;
/* Remove IV and ICV */
memmove(skb->data + 8, skb->data, hdr_len);
skb_pull(skb, 8);
skb_trim(skb, skb->len - 4);
return keyidx;
}
static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr,
u8 *data, size_t data_len, u8 *mic)
{
SHASH_DESC_ON_STACK(desc, tfm_michael);
int err;
desc->tfm = tfm_michael;
if (crypto_shash_setkey(tfm_michael, key, 8))
return -1;
err = crypto_shash_init(desc);
if (err)
goto out;
err = crypto_shash_update(desc, hdr, 16);
if (err)
goto out;
err = crypto_shash_update(desc, data, data_len);
if (err)
goto out;
err = crypto_shash_final(desc, mic);
out:
shash_desc_zero(desc);
return err;
}
static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
{
struct rtl_80211_hdr_4addr *hdr11;
hdr11 = (struct rtl_80211_hdr_4addr *)skb->data;
switch (le16_to_cpu(hdr11->frame_ctl) &
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
case IEEE80211_FCTL_TODS:
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
case IEEE80211_FCTL_FROMDS:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
break;
case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
break;
default:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
}
hdr[12] = 0; /* priority */
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
}
static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 *pos;
struct rtl_80211_hdr_4addr *hdr;
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
netdev_dbg(skb->dev, "Invalid packet for Michael MIC add "
"(tailroom=%d hdr_len=%d skb->len=%d)\n",
skb_tailroom(skb), hdr_len, skb->len);
return -1;
}
michael_mic_hdr(skb, tkey->tx_hdr);
// { david, 2006.9.1
// fix the wpa process with wmm enabled.
if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
// }
pos = skb_put(skb, 8);
if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
return -1;
return 0;
}
static void ieee80211_michael_mic_failure(struct net_device *dev,
struct rtl_80211_hdr_4addr *hdr,
int keyidx)
{
union iwreq_data wrqu;
struct iw_michaelmicfailure ev;
/* TODO: needed parameters: count, keyid, key type, TSC */
memset(&ev, 0, sizeof(ev));
ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
if (hdr->addr1[0] & 0x01)
ev.flags |= IW_MICFAILURE_GROUP;
else
ev.flags |= IW_MICFAILURE_PAIRWISE;
ev.src_addr.sa_family = ARPHRD_ETHER;
memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = sizeof(ev);
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
}
static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
u8 mic[8];
struct rtl_80211_hdr_4addr *hdr;
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
if (!tkey->key_set)
return -1;
michael_mic_hdr(skb, tkey->rx_hdr);
// { david, 2006.9.1
// fix the wpa process with wmm enabled.
if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
// }
if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
return -1;
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
struct rtl_80211_hdr_4addr *hdr;
hdr = (struct rtl_80211_hdr_4addr *)skb->data;
netdev_dbg(skb->dev, "Michael MIC verification failed for "
"MSDU from %pM keyidx=%d\n",
hdr->addr2, keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
return -1;
}
/*
* Update TSC counters for RX now that the packet verification has
* completed.
*/
tkey->rx_iv32 = tkey->rx_iv32_new;
tkey->rx_iv16 = tkey->rx_iv16_new;
skb_trim(skb, skb->len - 8);
return 0;
}
static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
int keyidx;
struct crypto_shash *tfm = tkey->tx_tfm_michael;
struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
keyidx = tkey->key_idx;
memset(tkey, 0, sizeof(*tkey));
tkey->key_idx = keyidx;
tkey->tx_tfm_michael = tfm;
tkey->rx_tfm_michael = tfm3;
if (len == TKIP_KEY_LEN) {
memcpy(tkey->key, key, TKIP_KEY_LEN);
tkey->key_set = 1;
tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
if (seq) {
tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
(seq[3] << 8) | seq[2];
tkey->rx_iv16 = (seq[1] << 8) | seq[0];
}
} else if (len == 0)
tkey->key_set = 0;
else
return -1;
return 0;
}
static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
if (len < TKIP_KEY_LEN)
return 0;
if (!tkey->key_set)
return 0;
memcpy(key, tkey->key, TKIP_KEY_LEN);
if (seq) {
/* Return the sequence number of the last transmitted frame. */
u16 iv16 = tkey->tx_iv16;
u32 iv32 = tkey->tx_iv32;
if (iv16 == 0)
iv32--;
iv16--;
seq[0] = tkey->tx_iv16;
seq[1] = tkey->tx_iv16 >> 8;
seq[2] = tkey->tx_iv32;
seq[3] = tkey->tx_iv32 >> 8;
seq[4] = tkey->tx_iv32 >> 16;
seq[5] = tkey->tx_iv32 >> 24;
}
return TKIP_KEY_LEN;
}
static char *ieee80211_tkip_print_stats(char *p, void *priv)
{
struct ieee80211_tkip_data *tkip = priv;
p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
"tx_pn=%02x%02x%02x%02x%02x%02x "
"rx_pn=%02x%02x%02x%02x%02x%02x "
"replays=%d icv_errors=%d local_mic_failures=%d\n",
tkip->key_idx, tkip->key_set,
(tkip->tx_iv32 >> 24) & 0xff,
(tkip->tx_iv32 >> 16) & 0xff,
(tkip->tx_iv32 >> 8) & 0xff,
tkip->tx_iv32 & 0xff,
(tkip->tx_iv16 >> 8) & 0xff,
tkip->tx_iv16 & 0xff,
(tkip->rx_iv32 >> 24) & 0xff,
(tkip->rx_iv32 >> 16) & 0xff,
(tkip->rx_iv32 >> 8) & 0xff,
tkip->rx_iv32 & 0xff,
(tkip->rx_iv16 >> 8) & 0xff,
tkip->rx_iv16 & 0xff,
tkip->dot11RSNAStatsTKIPReplays,
tkip->dot11RSNAStatsTKIPICVErrors,
tkip->dot11RSNAStatsTKIPLocalMICFailures);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
.name = "TKIP",
.init = ieee80211_tkip_init,
.deinit = ieee80211_tkip_deinit,
.encrypt_mpdu = ieee80211_tkip_encrypt,
.decrypt_mpdu = ieee80211_tkip_decrypt,
.encrypt_msdu = ieee80211_michael_mic_add,
.decrypt_msdu = ieee80211_michael_mic_verify,
.set_key = ieee80211_tkip_set_key,
.get_key = ieee80211_tkip_get_key,
.print_stats = ieee80211_tkip_print_stats,
.extra_prefix_len = 4 + 4, /* IV + ExtIV */
.extra_postfix_len = 8 + 4, /* MIC + ICV */
.owner = THIS_MODULE,
};
int __init ieee80211_crypto_tkip_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
}
void ieee80211_crypto_tkip_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
}

View File

@ -1,247 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Host AP crypt: host-based WEP encryption implementation for Host AP driver
*
* Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*/
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include "ieee80211.h"
#include <crypto/arc4.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: WEP");
MODULE_LICENSE("GPL");
struct prism2_wep_data {
u32 iv;
#define WEP_KEY_LEN 13
u8 key[WEP_KEY_LEN + 1];
u8 key_len;
u8 key_idx;
struct arc4_ctx rx_ctx_arc4;
struct arc4_ctx tx_ctx_arc4;
};
static void *prism2_wep_init(int keyidx)
{
struct prism2_wep_data *priv;
if (fips_enabled)
return NULL;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return NULL;
priv->key_idx = keyidx;
/* start WEP IV from a random value */
get_random_bytes(&priv->iv, 4);
return priv;
}
static void prism2_wep_deinit(void *priv)
{
kfree_sensitive(priv);
}
/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
* for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
* so the payload length increases with 8 bytes.
*
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
u32 klen, len;
u8 key[WEP_KEY_LEN + 3];
u8 *pos;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u32 crc;
u8 *icv;
if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
len = skb->len - hdr_len;
pos = skb_push(skb, 4);
memmove(pos, pos + 4, hdr_len);
pos += hdr_len;
klen = 3 + wep->key_len;
wep->iv++;
/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
* scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
* can be used to speedup attacks, so avoid using them.
*/
if ((wep->iv & 0xff00) == 0xff00) {
u8 B = (wep->iv >> 16) & 0xff;
if (B >= 3 && B < klen)
wep->iv += 0x0100;
}
/* Prepend 24-bit IV to RC4 key and TX frame */
*pos++ = key[0] = (wep->iv >> 16) & 0xff;
*pos++ = key[1] = (wep->iv >> 8) & 0xff;
*pos++ = key[2] = wep->iv & 0xff;
*pos++ = wep->key_idx << 6;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
if (!tcb_desc->bHwSec) {
/* Append little-endian CRC32 and encrypt it to produce ICV */
crc = ~crc32_le(~0, pos, len);
icv = skb_put(skb, 4);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
arc4_setkey(&wep->tx_ctx_arc4, key, klen);
arc4_crypt(&wep->tx_ctx_arc4, pos, pos, len + 4);
}
return 0;
}
/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
* the frame: IV (4 bytes), encrypted payload (including SNAP header),
* ICV (4 bytes). len includes both IV and ICV.
*
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
* failure. If frame is OK, IV and ICV will be removed.
*/
static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
u32 klen, plen;
u8 key[WEP_KEY_LEN + 3];
u8 keyidx, *pos;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u32 crc;
u8 icv[4];
if (skb->len < hdr_len + 8)
return -1;
pos = skb->data + hdr_len;
key[0] = *pos++;
key[1] = *pos++;
key[2] = *pos++;
keyidx = *pos++ >> 6;
if (keyidx != wep->key_idx)
return -1;
klen = 3 + wep->key_len;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
/* Apply RC4 to data and compute CRC32 over decrypted data */
plen = skb->len - hdr_len - 8;
if (!tcb_desc->bHwSec) {
arc4_setkey(&wep->rx_ctx_arc4, key, klen);
arc4_crypt(&wep->rx_ctx_arc4, pos, pos, plen + 4);
crc = ~crc32_le(~0, pos, plen);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
if (memcmp(icv, pos + plen, 4) != 0) {
/* ICV mismatch - drop frame */
return -2;
}
}
/* Remove IV and ICV */
memmove(skb->data + 4, skb->data, hdr_len);
skb_pull(skb, 4);
skb_trim(skb, skb->len - 4);
return 0;
}
static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < 0 || len > WEP_KEY_LEN)
return -1;
memcpy(wep->key, key, len);
wep->key_len = len;
return 0;
}
static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < wep->key_len)
return 0;
memcpy(key, wep->key, wep->key_len);
return wep->key_len;
}
static char *prism2_wep_print_stats(char *p, void *priv)
{
struct prism2_wep_data *wep = priv;
p += sprintf(p, "key[%d] alg=WEP len=%d\n",
wep->key_idx, wep->key_len);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
.name = "WEP",
.init = prism2_wep_init,
.deinit = prism2_wep_deinit,
.encrypt_mpdu = prism2_wep_encrypt,
.decrypt_mpdu = prism2_wep_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = prism2_wep_set_key,
.get_key = prism2_wep_get_key,
.print_stats = prism2_wep_print_stats,
.extra_prefix_len = 4, /* IV */
.extra_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};
int __init ieee80211_crypto_wep_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
}
void ieee80211_crypto_wep_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
}

View File

@ -1,287 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*******************************************************************************
*
* Copyright(c) 2004 Intel Corporation. All rights reserved.
*
* Portions of this file are based on the WEP enablement code provided by the
* Host AP project hostap-drivers v0.1.3
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
******************************************************************************/
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include <net/arp.h>
#include "ieee80211.h"
MODULE_DESCRIPTION("802.11 data/management/control stack");
MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
MODULE_LICENSE("GPL");
#define DRV_NAME "ieee80211"
static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
{
if (ieee->networks)
return 0;
ieee->networks = kcalloc(MAX_NETWORK_COUNT,
sizeof(struct ieee80211_network),
GFP_KERNEL);
if (!ieee->networks) {
netdev_warn(ieee->dev, "Out of memory allocating beacons\n");
return -ENOMEM;
}
return 0;
}
static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
{
if (!ieee->networks)
return;
kfree(ieee->networks);
ieee->networks = NULL;
}
static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;
INIT_LIST_HEAD(&ieee->network_free_list);
INIT_LIST_HEAD(&ieee->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++)
list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
}
struct net_device *alloc_ieee80211(int sizeof_priv)
{
struct ieee80211_device *ieee;
struct net_device *dev;
int i, err;
IEEE80211_DEBUG_INFO("Initializing...\n");
dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
if (!dev) {
IEEE80211_ERROR("Unable to network device.\n");
goto failed;
}
ieee = netdev_priv(dev);
ieee->dev = dev;
err = ieee80211_networks_allocate(ieee);
if (err) {
IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
err);
goto failed;
}
ieee80211_networks_initialize(ieee);
/* Default fragmentation threshold is maximum payload size */
ieee->fts = DEFAULT_FTS;
ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
ieee->open_wep = 1;
/* Default to enabling full open WEP with host based encrypt/decrypt */
ieee->host_encrypt = 1;
ieee->host_decrypt = 1;
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
INIT_LIST_HEAD(&ieee->crypt_deinit_list);
timer_setup(&ieee->crypt_deinit_timer, ieee80211_crypt_deinit_handler,
0);
spin_lock_init(&ieee->lock);
spin_lock_init(&ieee->wpax_suitlist_lock);
spin_lock_init(&ieee->bw_spinlock);
spin_lock_init(&ieee->reorder_spinlock);
/* added by WB */
atomic_set(&ieee->atm_chnlop, 0);
atomic_set(&ieee->atm_swbw, 0);
ieee->wpax_type_set = 0;
ieee->wpa_enabled = 0;
ieee->tkip_countermeasures = 0;
ieee->drop_unencrypted = 0;
ieee->privacy_invoked = 0;
ieee->ieee802_1x = 1;
ieee->raw_tx = 0;
//ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead.
ieee->hwsec_active = 0; /* disable hwsec, switch it on when necessary. */
ieee80211_softmac_init(ieee);
ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
if (!ieee->pHTInfo) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
/* By this point in code ieee80211_networks_allocate() has been
* successfully called so the memory allocated should be freed
*/
ieee80211_networks_free(ieee);
goto failed;
}
HTUpdateDefaultSetting(ieee);
HTInitializeHTInfo(ieee); /* may move to other place. */
TSInitialize(ieee);
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
for (i = 0; i < 17; i++) {
ieee->last_rxseq_num[i] = -1;
ieee->last_rxfrag_num[i] = -1;
ieee->last_packet_time[i] = 0;
}
return dev;
failed:
if (dev)
free_netdev(dev);
return NULL;
}
void free_ieee80211(struct net_device *dev)
{
struct ieee80211_device *ieee = netdev_priv(dev);
int i;
/* struct list_head *p, *q; */
// del_timer_sync(&ieee->SwBwTimer);
kfree(ieee->pHTInfo);
ieee->pHTInfo = NULL;
RemoveAllTS(ieee);
ieee80211_softmac_free(ieee);
del_timer_sync(&ieee->crypt_deinit_timer);
ieee80211_crypt_deinit_entries(ieee, 1);
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
if (crypt->ops)
crypt->ops->deinit(crypt->priv);
kfree(crypt);
ieee->crypt[i] = NULL;
}
}
ieee80211_networks_free(ieee);
free_netdev(dev);
}
#ifdef CONFIG_IEEE80211_DEBUG
u32 ieee80211_debug_level;
static int debug = // IEEE80211_DL_INFO |
// IEEE80211_DL_WX |
// IEEE80211_DL_SCAN |
// IEEE80211_DL_STATE |
// IEEE80211_DL_MGMT |
// IEEE80211_DL_FRAG |
// IEEE80211_DL_EAP |
// IEEE80211_DL_DROP |
// IEEE80211_DL_TX |
// IEEE80211_DL_RX |
//IEEE80211_DL_QOS |
// IEEE80211_DL_HT |
// IEEE80211_DL_TS |
// IEEE80211_DL_BA |
// IEEE80211_DL_REORDER|
// IEEE80211_DL_TRACE |
//IEEE80211_DL_DATA |
IEEE80211_DL_ERR /* awayls open this flags to show error out */
;
static struct proc_dir_entry *ieee80211_proc;
static int show_debug_level(struct seq_file *m, void *v)
{
seq_printf(m, "0x%08X\n", ieee80211_debug_level);
return 0;
}
static ssize_t write_debug_level(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
unsigned long val;
int err = kstrtoul_from_user(buffer, count, 0, &val);
if (err)
return err;
ieee80211_debug_level = val;
return count;
}
static int open_debug_level(struct inode *inode, struct file *file)
{
return single_open(file, show_debug_level, NULL);
}
static const struct proc_ops debug_level_proc_ops = {
.proc_open = open_debug_level,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = write_debug_level,
.proc_release = single_release,
};
int __init ieee80211_debug_init(void)
{
struct proc_dir_entry *e;
ieee80211_debug_level = debug;
ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
if (!ieee80211_proc) {
IEEE80211_ERROR("Unable to create " DRV_NAME
" proc directory\n");
return -EIO;
}
e = proc_create("debug_level", 0644, ieee80211_proc, &debug_level_proc_ops);
if (!e) {
remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL;
return -EIO;
}
return 0;
}
void ieee80211_debug_exit(void)
{
if (ieee80211_proc) {
remove_proc_entry("debug_level", ieee80211_proc);
remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL;
}
}
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,598 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/* IEEE 802.11 SoftMAC layer
* Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
*
* Mostly extracted from the rtl8180-sa2400 driver for the
* in-kernel generic ieee802.11 stack.
*
* Some pieces of code might be stolen from ipw2100 driver
* copyright of who own it's copyright ;-)
*
* PS wx handler mostly stolen from hostap, copyright who
* own it's copyright ;-)
*/
#include <linux/etherdevice.h>
#include "ieee80211.h"
#include "dot11d.h"
/* FIXME: add A freqs */
const long ieee80211_wlan_frequencies[] = {
2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467,
2472, 2484
};
EXPORT_SYMBOL(ieee80211_wlan_frequencies);
int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret;
struct iw_freq *fwrq = &wrqu->freq;
mutex_lock(&ieee->wx_mutex);
if (ieee->iw_mode == IW_MODE_INFRA) {
ret = -EOPNOTSUPP;
goto out;
}
/* if setting by freq convert to channel */
if (fwrq->e == 1) {
if ((fwrq->m >= (int)2.412e8 &&
fwrq->m <= (int)2.487e8)) {
int f = fwrq->m / 100000;
int c = 0;
while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
c++;
/* hack to fall through */
fwrq->e = 0;
fwrq->m = c + 1;
}
}
if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
ret = -EOPNOTSUPP;
goto out;
} else { /* Set the channel */
if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) {
ret = -EINVAL;
goto out;
}
ieee->current_network.channel = fwrq->m;
ieee->set_chan(ieee->dev, ieee->current_network.channel);
if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
if (ieee->state == IEEE80211_LINKED) {
ieee80211_stop_send_beacons(ieee);
ieee80211_start_send_beacons(ieee);
}
}
ret = 0;
out:
mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_freq);
int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct iw_freq *fwrq = &wrqu->freq;
if (ieee->current_network.channel == 0)
return -1;
/* NM 0.7.0 will not accept channel any more. */
fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel - 1] * 100000;
fwrq->e = 1;
/* fwrq->m = ieee->current_network.channel; */
/* fwrq->e = 0; */
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_freq);
int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
unsigned long flags;
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->wap_set == 0)
eth_zero_addr(wrqu->ap_addr.sa_data);
else
memcpy(wrqu->ap_addr.sa_data,
ieee->current_network.bssid, ETH_ALEN);
spin_unlock_irqrestore(&ieee->lock, flags);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_wap);
int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
int ret = 0;
unsigned long flags;
short ifup = ieee->proto_started; /* dev->flags & IFF_UP; */
struct sockaddr *temp = (struct sockaddr *)awrq;
ieee->sync_scan_hurryup = 1;
mutex_lock(&ieee->wx_mutex);
/* use ifconfig hw ether */
if (ieee->iw_mode == IW_MODE_MASTER) {
ret = -1;
goto out;
}
if (temp->sa_family != ARPHRD_ETHER) {
ret = -EINVAL;
goto out;
}
if (ifup)
ieee80211_stop_protocol(ieee);
/* just to avoid to give inconsistent infos in the
* get wx method. not really needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
ieee->wap_set = !is_zero_ether_addr(temp->sa_data);
spin_unlock_irqrestore(&ieee->lock, flags);
if (ifup)
ieee80211_start_protocol(ieee);
out:
mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_wap);
int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a, union iwreq_data *wrqu, char *b)
{
int len, ret = 0;
unsigned long flags;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->current_network.ssid[0] == '\0' ||
ieee->current_network.ssid_len == 0) {
ret = -1;
goto out;
}
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->ssid_set == 0) {
ret = -1;
goto out;
}
len = ieee->current_network.ssid_len;
wrqu->essid.length = len;
strncpy(b, ieee->current_network.ssid, len);
wrqu->essid.flags = 1;
out:
spin_unlock_irqrestore(&ieee->lock, flags);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_get_essid);
int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
u32 target_rate = wrqu->bitrate.value;
ieee->rate = target_rate / 100000;
/* FIXME: we might want to limit rate also in management protocols. */
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_rate);
int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
u32 tmp_rate;
tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
wrqu->bitrate.value = tmp_rate * 500000;
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_rate);
int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
if (wrqu->rts.disabled || !wrqu->rts.fixed) {
ieee->rts = DEFAULT_RTS_THRESHOLD;
} else {
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
wrqu->rts.value > MAX_RTS_THRESHOLD)
return -EINVAL;
ieee->rts = wrqu->rts.value;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_rts);
int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
wrqu->rts.value = ieee->rts;
wrqu->rts.fixed = 0; /* no auto select */
wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_rts);
int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
ieee->sync_scan_hurryup = 1;
mutex_lock(&ieee->wx_mutex);
if (wrqu->mode == ieee->iw_mode)
goto out;
if (wrqu->mode == IW_MODE_MONITOR)
ieee->dev->type = ARPHRD_IEEE80211;
else
ieee->dev->type = ARPHRD_ETHER;
if (!ieee->proto_started) {
ieee->iw_mode = wrqu->mode;
} else {
ieee80211_stop_protocol(ieee);
ieee->iw_mode = wrqu->mode;
ieee80211_start_protocol(ieee);
}
out:
mutex_unlock(&ieee->wx_mutex);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_mode);
void ieee80211_wx_sync_scan_wq(struct work_struct *work)
{
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
short chan;
enum ht_extension_chan_offset chan_offset = 0;
enum ht_channel_width bandwidth = 0;
int b40M = 0;
chan = ieee->current_network.channel;
netif_carrier_off(ieee->dev);
if (ieee->data_hard_stop)
ieee->data_hard_stop(ieee->dev);
ieee80211_stop_send_beacons(ieee);
ieee->state = IEEE80211_LINKED_SCANNING;
ieee->link_change(ieee->dev);
ieee->InitialGainHandler(ieee->dev, IG_Backup);
if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
b40M = 1;
chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz;
printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
}
ieee80211_start_scan_syncro(ieee);
if (b40M) {
printk("Scan in 20M, back to 40M\n");
if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
ieee->set_chan(ieee->dev, chan + 2);
else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
ieee->set_chan(ieee->dev, chan - 2);
else
ieee->set_chan(ieee->dev, chan);
ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
} else {
ieee->set_chan(ieee->dev, chan);
}
ieee->InitialGainHandler(ieee->dev, IG_Restore);
ieee->state = IEEE80211_LINKED;
ieee->link_change(ieee->dev);
/* To prevent the immediately calling watch_dog after scan. */
if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
}
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
ieee80211_start_send_beacons(ieee);
netif_carrier_on(ieee->dev);
mutex_unlock(&ieee->wx_mutex);
}
int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret = 0;
mutex_lock(&ieee->wx_mutex);
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
ret = -1;
goto out;
}
if (ieee->state == IEEE80211_LINKED) {
queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
/* intentionally forget to up sem */
return 0;
}
out:
mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_scan);
int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
int ret = 0, len;
short proto_started;
unsigned long flags;
ieee->sync_scan_hurryup = 1;
mutex_lock(&ieee->wx_mutex);
proto_started = ieee->proto_started;
if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
goto out;
}
if (ieee->iw_mode == IW_MODE_MONITOR) {
ret = -1;
goto out;
}
if (proto_started)
ieee80211_stop_protocol(ieee);
/* this is just to be sure that the GET wx callback
* has consisten infos. not needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
if (wrqu->essid.flags && wrqu->essid.length) {
/* first flush current network.ssid */
len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE;
strncpy(ieee->current_network.ssid, extra, len + 1);
ieee->current_network.ssid_len = len + 1;
ieee->ssid_set = 1;
} else {
ieee->ssid_set = 0;
ieee->current_network.ssid[0] = '\0';
ieee->current_network.ssid_len = 0;
}
spin_unlock_irqrestore(&ieee->lock, flags);
if (proto_started)
ieee80211_start_protocol(ieee);
out:
mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_essid);
int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
wrqu->mode = ieee->iw_mode;
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_mode);
int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int *parms = (int *)extra;
int enable = (parms[0] > 0);
short prev = ieee->raw_tx;
mutex_lock(&ieee->wx_mutex);
if (enable)
ieee->raw_tx = 1;
else
ieee->raw_tx = 0;
netdev_info(ieee->dev, "raw TX is %s\n",
ieee->raw_tx ? "enabled" : "disabled");
if (ieee->iw_mode == IW_MODE_MONITOR) {
if (prev == 0 && ieee->raw_tx) {
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
netif_carrier_on(ieee->dev);
}
if (prev && ieee->raw_tx == 1)
netif_carrier_off(ieee->dev);
}
mutex_unlock(&ieee->wx_mutex);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_rawtx);
int ieee80211_wx_get_name(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
strscpy(wrqu->name, "802.11", IFNAMSIZ);
if (ieee->modulation & IEEE80211_CCK_MODULATION) {
strlcat(wrqu->name, "b", IFNAMSIZ);
if (ieee->modulation & IEEE80211_OFDM_MODULATION)
strlcat(wrqu->name, "/g", IFNAMSIZ);
} else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
strlcat(wrqu->name, "g", IFNAMSIZ);
}
if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
strlcat(wrqu->name, "/n", IFNAMSIZ);
if ((ieee->state == IEEE80211_LINKED) ||
(ieee->state == IEEE80211_LINKED_SCANNING))
strlcat(wrqu->name, " linked", IFNAMSIZ);
else if (ieee->state != IEEE80211_NOLINK)
strlcat(wrqu->name, " link..", IFNAMSIZ);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_name);
/* this is mostly stolen from hostap */
int ieee80211_wx_set_power(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
mutex_lock(&ieee->wx_mutex);
if (wrqu->power.disabled) {
ieee->ps = IEEE80211_PS_DISABLED;
goto exit;
}
if (wrqu->power.flags & IW_POWER_TIMEOUT) {
/* ieee->ps_period = wrqu->power.value / 1000; */
ieee->ps_timeout = wrqu->power.value / 1000;
}
if (wrqu->power.flags & IW_POWER_PERIOD) {
/* ieee->ps_timeout = wrqu->power.value / 1000; */
ieee->ps_period = wrqu->power.value / 1000;
/* wrq->value / 1024; */
}
switch (wrqu->power.flags & IW_POWER_MODE) {
case IW_POWER_UNICAST_R:
ieee->ps = IEEE80211_PS_UNICAST;
break;
case IW_POWER_MULTICAST_R:
ieee->ps = IEEE80211_PS_MBCAST;
break;
case IW_POWER_ALL_R:
ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
break;
case IW_POWER_ON:
/* ieee->ps = IEEE80211_PS_DISABLED; */
break;
default:
ret = -EINVAL;
goto exit;
}
exit:
mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_power);
/* this is stolen from hostap */
int ieee80211_wx_get_power(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
mutex_lock(&ieee->wx_mutex);
if (ieee->ps == IEEE80211_PS_DISABLED) {
wrqu->power.disabled = 1;
goto exit;
}
wrqu->power.disabled = 0;
if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
wrqu->power.flags = IW_POWER_TIMEOUT;
wrqu->power.value = ieee->ps_timeout * 1000;
} else {
/* ret = -EOPNOTSUPP; */
/* goto exit; */
wrqu->power.flags = IW_POWER_PERIOD;
wrqu->power.value = ieee->ps_period * 1000;
/* ieee->current_network.dtim_period * ieee->current_network.beacon_interval * 1024; */
}
if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST))
wrqu->power.flags |= IW_POWER_ALL_R;
else if (ieee->ps & IEEE80211_PS_MBCAST)
wrqu->power.flags |= IW_POWER_MULTICAST_R;
else
wrqu->power.flags |= IW_POWER_UNICAST_R;
exit:
mutex_unlock(&ieee->wx_mutex);
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_power);

View File

@ -1,839 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
*
* Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* Few modifications for Realtek's Wi-Fi drivers by
* Andrea Merello <andrea.merello@gmail.com>
*
* A special thanks goes to Realtek for their support !
*
******************************************************************************/
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include <linux/if_vlan.h>
#include "ieee80211.h"
/*
*
*
* 802.11 Data Frame
*
*
* 802.11 frame_contorl for data frames - 2 bytes
* ,-----------------------------------------------------------------------------------------.
* bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
* |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
* val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
* |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
* desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
* | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
* '-----------------------------------------------------------------------------------------'
* /\
* |
* 802.11 Data Frame |
* ,--------- 'ctrl' expands to >-----------'
* |
* ,--'---,-------------------------------------------------------------.
* Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
* |------|------|---------|---------|---------|------|---------|------|
* Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
* | | tion | (BSSID) | | | ence | data | |
* `--------------------------------------------------| |------'
* Total: 28 non-data bytes `----.----'
* |
* .- 'Frame data' expands to <---------------------------'
* |
* V
* ,---------------------------------------------------.
* Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
* |------|------|---------|----------|------|---------|
* Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
* | DSAP | SSAP | | | | Packet |
* | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
* `-----------------------------------------| |
* Total: 8 non-data bytes `----.----'
* |
* .- 'IP Packet' expands, if WEP enabled, to <--'
* |
* V
* ,-----------------------.
* Bytes | 4 | 0-2296 | 4 |
* |-----|-----------|-----|
* Desc. | IV | Encrypted | ICV |
* | | IP Packet | |
* `-----------------------'
* Total: 8 non-data bytes
*
*
* 802.3 Ethernet Data Frame
*
* ,-----------------------------------------.
* Bytes | 6 | 6 | 2 | Variable | 4 |
* |-------|-------|------|-----------|------|
* Desc. | Dest. | Source| Type | IP Packet | fcs |
* | MAC | MAC | | | |
* `-----------------------------------------'
* Total: 18 non-data bytes
*
* In the event that fragmentation is required, the incoming payload is split into
* N parts of size ieee->fts. The first fragment contains the SNAP header and the
* remaining packets are just data.
*
* If encryption is enabled, each fragment payload size is reduced by enough space
* to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
* So if you have 1500 bytes of payload with ieee->fts set to 500 without
* encryption it will take 3 frames. With WEP it will take 4 frames as the
* payload of each frame is reduced to 492 bytes.
*
* SKB visualization
*
* ,- skb->data
* |
* | ETHERNET HEADER ,-<-- PAYLOAD
* | | 14 bytes from skb->data
* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
* | | | |
* |,-Dest.--. ,--Src.---. | | |
* | 6 bytes| | 6 bytes | | | |
* v | | | | | |
* 0 | v 1 | v | v 2
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* ^ | ^ | ^ |
* | | | | | |
* | | | | `T' <---- 2 bytes for Type
* | | | |
* | | '---SNAP--' <-------- 6 bytes for SNAP
* | |
* `-IV--' <-------------------- 4 bytes for IV (WEP)
*
* SNAP HEADER
*
*/
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
{
struct ieee80211_snap_hdr *snap;
u8 *oui;
snap = (struct ieee80211_snap_hdr *)data;
snap->dsap = 0xaa;
snap->ssap = 0xaa;
snap->ctrl = 0x03;
if (h_proto == 0x8137 || h_proto == 0x80f3)
oui = P802_1H_OUI;
else
oui = RFC1042_OUI;
snap->oui[0] = oui[0];
snap->oui[1] = oui[1];
snap->oui[2] = oui[2];
*(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
return SNAP_SIZE + sizeof(u16);
}
int ieee80211_encrypt_fragment(
struct ieee80211_device *ieee,
struct sk_buff *frag,
int hdr_len)
{
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
int res;
if (!(crypt && crypt->ops)) {
printk("=========>%s(), crypt is null\n", __func__);
return -1;
}
if (ieee->tkip_countermeasures &&
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
struct rtl_80211_hdr_3addrqos *header;
header = (struct rtl_80211_hdr_3addrqos *)frag->data;
netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
"TX packet to %pM\n", header->addr1);
}
return -1;
}
/* To encrypt, frame format is:
* IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
*/
// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
* call both MSDU and MPDU encryption functions from here.
*/
atomic_inc(&crypt->refcnt);
res = 0;
if (crypt->ops->encrypt_msdu)
res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
if (res == 0 && crypt->ops->encrypt_mpdu)
res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
atomic_dec(&crypt->refcnt);
if (res < 0) {
netdev_info(ieee->dev, "Encryption failed: len=%d.\n",
frag->len);
ieee->ieee_stats.tx_discards++;
return -1;
}
return 0;
}
void ieee80211_txb_free(struct ieee80211_txb *txb)
{
//int i;
if (unlikely(!txb))
return;
kfree(txb);
}
EXPORT_SYMBOL(ieee80211_txb_free);
static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
gfp_t gfp_mask)
{
struct ieee80211_txb *txb;
int i;
txb = kmalloc(
sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
gfp_mask);
if (!txb)
return NULL;
memset(txb, 0, sizeof(struct ieee80211_txb));
txb->nr_frags = nr_frags;
txb->frag_size = __cpu_to_le16(txb_size);
for (i = 0; i < nr_frags; i++) {
txb->fragments[i] = dev_alloc_skb(txb_size);
if (unlikely(!txb->fragments[i])) {
i--;
break;
}
memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
}
if (unlikely(i != nr_frags)) {
while (i >= 0)
dev_kfree_skb_any(txb->fragments[i--]);
kfree(txb);
return NULL;
}
return txb;
}
// Classify the to-be send data packet
// Need to acquire the sent queue index.
static int
ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
{
struct ethhdr *eth;
struct iphdr *ip;
eth = (struct ethhdr *)skb->data;
if (eth->h_proto != htons(ETH_P_IP))
return 0;
ip = ip_hdr(skb);
switch (ip->tos & 0xfc) {
case 0x20:
return 2;
case 0x40:
return 1;
case 0x60:
return 3;
case 0x80:
return 4;
case 0xa0:
return 5;
case 0xc0:
return 6;
case 0xe0:
return 7;
default:
return 0;
}
}
static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee,
struct sk_buff *skb, struct cb_desc *tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
struct tx_ts_record *pTxTs = NULL;
struct rtl_80211_hdr_1addr *hdr = (struct rtl_80211_hdr_1addr *)skb->data;
if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
return;
if (!IsQoSDataFrame(skb->data))
return;
if (is_multicast_ether_addr(hdr->addr1))
return;
//check packet and mode later
if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
return;
if (pHTInfo->bCurrentAMPDUEnable) {
if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) {
printk("===>can't get TS\n");
return;
}
if (!pTxTs->tx_admitted_ba_record.valid) {
TsStartAddBaProcess(ieee, pTxTs);
goto FORCED_AGG_SETTING;
} else if (!pTxTs->using_ba) {
if (SN_LESS(pTxTs->tx_admitted_ba_record.start_seq_ctrl.field.seq_num, (pTxTs->tx_cur_seq + 1) % 4096))
pTxTs->using_ba = true;
else
goto FORCED_AGG_SETTING;
}
if (ieee->iw_mode == IW_MODE_INFRA) {
tcb_desc->bAMPDUEnable = true;
tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
}
}
FORCED_AGG_SETTING:
switch (pHTInfo->ForcedAMPDUMode) {
case HT_AGG_AUTO:
break;
case HT_AGG_FORCE_ENABLE:
tcb_desc->bAMPDUEnable = true;
tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
break;
case HT_AGG_FORCE_DISABLE:
tcb_desc->bAMPDUEnable = false;
tcb_desc->ampdu_density = 0;
tcb_desc->ampdu_factor = 0;
break;
}
return;
}
static void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device *ieee,
struct cb_desc *tcb_desc)
{
tcb_desc->bUseShortPreamble = false;
if (tcb_desc->data_rate == 2) {//// 1M can only use Long Preamble. 11B spec
return;
} else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
tcb_desc->bUseShortPreamble = true;
}
return;
}
static void
ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
tcb_desc->bUseShortGI = false;
if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
return;
if (pHTInfo->bForcedShortGI) {
tcb_desc->bUseShortGI = true;
return;
}
if (pHTInfo->bCurBW40MHz && pHTInfo->bCurShortGI40MHz)
tcb_desc->bUseShortGI = true;
else if (!pHTInfo->bCurBW40MHz && pHTInfo->bCurShortGI20MHz)
tcb_desc->bUseShortGI = true;
}
static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee,
struct cb_desc *tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
tcb_desc->bPacketBW = false;
if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
return;
if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
return;
if ((tcb_desc->data_rate & 0x80) == 0) // If using legacy rate, it shall use 20MHz channel.
return;
//BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
tcb_desc->bPacketBW = true;
return;
}
static void ieee80211_query_protectionmode(struct ieee80211_device *ieee,
struct cb_desc *tcb_desc,
struct sk_buff *skb)
{
// Common Settings
tcb_desc->bRTSSTBC = false;
tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS
tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate.
tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz
if (tcb_desc->bBroadcast || tcb_desc->bMulticast) //only unicast frame will use rts/cts
return;
if (is_broadcast_ether_addr(skb->data + 16)) //check addr3 as infrastructure add3 is DA.
return;
if (ieee->mode < IEEE_N_24G) /* b, g mode */ {
// (1) RTS_Threshold is compared to the MPDU, not MSDU.
// (2) If there are more than one frag in this MSDU, only the first frag uses protection frame.
// Other fragments are protected by previous fragment.
// So we only need to check the length of first fragment.
if (skb->len > ieee->rts) {
tcb_desc->bRTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
} else if (ieee->current_network.buseprotection) {
// Use CTS-to-SELF in protection mode.
tcb_desc->bRTSEnable = true;
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
}
//otherwise return;
return;
} else { // 11n High throughput case.
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
while (true) {
//check ERP protection
if (ieee->current_network.buseprotection) {// CTS-to-SELF
tcb_desc->bRTSEnable = true;
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
break;
}
//check HT op mode
if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
u8 HTOpMode = pHTInfo->CurrentOpMode;
if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
(!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
tcb_desc->bRTSEnable = true;
break;
}
}
//check rts
if (skb->len > ieee->rts) {
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
tcb_desc->bRTSEnable = true;
break;
}
//to do list: check MIMO power save condition.
//check AMPDU aggregation for TXOP
if (tcb_desc->bAMPDUEnable) {
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
// According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
// throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
tcb_desc->bRTSEnable = false;
break;
}
//check IOT action
if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
tcb_desc->bRTSEnable = true;
break;
}
// Totally no protection case!!
goto NO_PROTECTION;
}
}
// For test , CTS replace with RTS
if (0) {
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
tcb_desc->bRTSEnable = true;
}
if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
tcb_desc->bUseShortPreamble = true;
if (ieee->mode == IW_MODE_MASTER)
goto NO_PROTECTION;
return;
NO_PROTECTION:
tcb_desc->bRTSEnable = false;
tcb_desc->bCTSEnable = false;
tcb_desc->rts_rate = 0;
tcb_desc->RTSSC = 0;
tcb_desc->bRTSBW = false;
}
static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee,
struct cb_desc *tcb_desc)
{
if (ieee->bTxDisableRateFallBack)
tcb_desc->bTxDisableRateFallBack = true;
if (ieee->bTxUseDriverAssingedRate)
tcb_desc->bTxUseDriverAssingedRate = true;
if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) {
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
tcb_desc->RATRIndex = 0;
}
}
static void ieee80211_query_seqnum(struct ieee80211_device *ieee,
struct sk_buff *skb, u8 *dst)
{
if (is_multicast_ether_addr(dst))
return;
if (IsQoSDataFrame(skb->data)) /* we deal qos data only */ {
struct tx_ts_record *pTS = NULL;
if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) {
return;
}
pTS->tx_cur_seq = (pTS->tx_cur_seq + 1) % 4096;
}
}
netdev_tx_t ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ieee80211_device *ieee = netdev_priv(dev);
struct ieee80211_txb *txb = NULL;
struct rtl_80211_hdr_3addrqos *frag_hdr;
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
unsigned long flags;
struct net_device_stats *stats = &ieee->stats;
int ether_type = 0, encrypt;
int bytes, fc, qos_ctl = 0, hdr_len;
struct sk_buff *skb_frag;
struct rtl_80211_hdr_3addrqos header = { /* Ensure zero initialized */
.duration_id = 0,
.seq_ctl = 0,
.qos_ctl = 0
};
u8 dest[ETH_ALEN], src[ETH_ALEN];
int qos_actived = ieee->current_network.qos_data.active;
struct ieee80211_crypt_data *crypt;
struct cb_desc *tcb_desc;
spin_lock_irqsave(&ieee->lock, flags);
/* If there is no driver handler to take the TXB, dont' bother
* creating it...
*/
if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) ||
((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
netdev_warn(ieee->dev, "No xmit handler.\n");
goto success;
}
if (likely(ieee->raw_tx == 0)) {
if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
netdev_warn(ieee->dev, "skb too small (%d).\n",
skb->len);
goto success;
}
memset(skb->cb, 0, sizeof(skb->cb));
ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
crypt = ieee->crypt[ieee->tx_keyidx];
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->host_encrypt && crypt && crypt->ops;
if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
stats->tx_dropped++;
goto success;
}
#ifdef CONFIG_IEEE80211_DEBUG
if (crypt && !encrypt && ether_type == ETH_P_PAE) {
struct eapol *eap = (struct eapol *)(skb->data +
sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
eap_get_type(eap->type));
}
#endif
/* Save source and destination addresses */
memcpy(&dest, skb->data, ETH_ALEN);
memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
/* Advance the SKB to the start of the payload */
skb_pull(skb, sizeof(struct ethhdr));
/* Determine total amount of storage required for TXB packets */
bytes = skb->len + SNAP_SIZE + sizeof(u16);
if (encrypt)
fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
else
fc = IEEE80211_FTYPE_DATA;
//if(ieee->current_network.QoS_Enable)
if (qos_actived)
fc |= IEEE80211_STYPE_QOS_DATA;
else
fc |= IEEE80211_STYPE_DATA;
if (ieee->iw_mode == IW_MODE_INFRA) {
fc |= IEEE80211_FCTL_TODS;
/* To DS: Addr1 = BSSID, Addr2 = SA,
* Addr3 = DA
*/
memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
memcpy(&header.addr2, &src, ETH_ALEN);
memcpy(&header.addr3, &dest, ETH_ALEN);
} else if (ieee->iw_mode == IW_MODE_ADHOC) {
/* not From/To DS: Addr1 = DA, Addr2 = SA,
* Addr3 = BSSID
*/
memcpy(&header.addr1, dest, ETH_ALEN);
memcpy(&header.addr2, src, ETH_ALEN);
memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
}
header.frame_ctl = cpu_to_le16(fc);
/* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented)
*/
if (is_multicast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
} else {
frag_size = ieee->fts;//default:392
qos_ctl = 0;
}
//if (ieee->current_network.QoS_Enable)
if (qos_actived) {
hdr_len = IEEE80211_3ADDR_LEN + 2;
skb->priority = ieee80211_classify(skb, &ieee->current_network);
qos_ctl |= skb->priority; //set in the ieee80211_classify
header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
} else {
hdr_len = IEEE80211_3ADDR_LEN;
}
/* Determine amount of payload per fragment. Regardless of if
* this stack is providing the full 802.11 header, one will
* eventually be affixed to this fragment -- so we must account for
* it when determining the amount of payload space.
*/
bytes_per_frag = frag_size - hdr_len;
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
/* Each fragment may need to have room for encryption pre/postfix */
if (encrypt)
bytes_per_frag -= crypt->ops->extra_prefix_len +
crypt->ops->extra_postfix_len;
/* Number of fragments is the total bytes_per_frag /
* payload_per_fragment
*/
nr_frags = bytes / bytes_per_frag;
bytes_last_frag = bytes % bytes_per_frag;
if (bytes_last_frag)
nr_frags++;
else
bytes_last_frag = bytes_per_frag;
/* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.)
*/
txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
if (unlikely(!txb)) {
netdev_warn(ieee->dev, "Could not allocate TXB\n");
goto failed;
}
txb->encrypted = encrypt;
txb->payload_size = __cpu_to_le16(bytes);
//if (ieee->current_network.QoS_Enable)
if (qos_actived)
txb->queue_index = UP2AC(skb->priority);
else
txb->queue_index = WME_AC_BK;
for (i = 0; i < nr_frags; i++) {
skb_frag = txb->fragments[i];
tcb_desc = (struct cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
if (qos_actived) {
skb_frag->priority = skb->priority;//UP2AC(skb->priority);
tcb_desc->queue_index = UP2AC(skb->priority);
} else {
skb_frag->priority = WME_AC_BK;
tcb_desc->queue_index = WME_AC_BK;
}
skb_reserve(skb_frag, ieee->tx_headroom);
if (encrypt) {
if (ieee->hwsec_active)
tcb_desc->bHwSec = 1;
else
tcb_desc->bHwSec = 0;
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
} else {
tcb_desc->bHwSec = 0;
}
frag_hdr = skb_put_data(skb_frag, &header, hdr_len);
/* If this is not the last fragment, then add the MOREFRAGS
* bit to the frame control
*/
if (i != nr_frags - 1) {
frag_hdr->frame_ctl = cpu_to_le16(
fc | IEEE80211_FCTL_MOREFRAGS);
bytes = bytes_per_frag;
} else {
/* The last fragment takes the remaining length */
bytes = bytes_last_frag;
}
//if(ieee->current_network.QoS_Enable)
if (qos_actived) {
// add 1 only indicate to corresponding seq number control 2006/7/12
frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority) + 1] << 4 | i);
} else {
frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4 | i);
}
/* Put a SNAP header on the first fragment */
if (i == 0) {
ieee80211_put_snap(
skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
ether_type);
bytes -= SNAP_SIZE + sizeof(u16);
}
skb_put_data(skb_frag, skb->data, bytes);
/* Advance the SKB... */
skb_pull(skb, bytes);
/* Encryption routine will move the header forward in order
* to insert the IV between the header and the payload
*/
if (encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4);
}
if (qos_actived) {
if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
else
ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
} else {
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
else
ieee->seq_ctrl[0]++;
}
} else {
if (unlikely(skb->len < sizeof(struct rtl_80211_hdr_3addr))) {
netdev_warn(ieee->dev, "skb too small (%d).\n",
skb->len);
goto success;
}
txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
if (!txb) {
netdev_warn(ieee->dev, "Could not allocate TXB\n");
goto failed;
}
txb->encrypted = 0;
txb->payload_size = __cpu_to_le16(skb->len);
skb_put_data(txb->fragments[0], skb->data, skb->len);
}
success:
//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
if (txb) {
tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->bTxEnableFwCalcDur = 1;
if (is_multicast_ether_addr(header.addr1))
tcb_desc->bMulticast = 1;
if (is_broadcast_ether_addr(header.addr1))
tcb_desc->bBroadcast = 1;
ieee80211_txrate_selectmode(ieee, tcb_desc);
if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
tcb_desc->data_rate = ieee->basic_rate;
else
tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
ieee80211_query_HTCapShortGI(ieee, tcb_desc);
ieee80211_query_BandwidthMode(ieee, tcb_desc);
ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
}
spin_unlock_irqrestore(&ieee->lock, flags);
dev_kfree_skb_any(skb);
if (txb) {
if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
ieee80211_softmac_xmit(txb, ieee);
} else {
if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
stats->tx_packets++;
stats->tx_bytes += __le16_to_cpu(txb->payload_size);
return NETDEV_TX_OK;
}
ieee80211_txb_free(txb);
}
}
return NETDEV_TX_OK;
failed:
spin_unlock_irqrestore(&ieee->lock, flags);
netif_stop_queue(dev);
stats->tx_errors++;
return 1;
}

View File

@ -1,810 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
Copyright(c) 2004 Intel Corporation. All rights reserved.
Portions of this file are based on the WEP enablement code provided by the
Host AP project hostap-drivers v0.1.3
Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
<jkmaline@cc.hut.fi>
Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************/
#include <linux/wireless.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/module.h>
#include "ieee80211.h"
struct modes_unit {
char *mode_string;
int mode_size;
};
static struct modes_unit ieee80211_modes[] = {
{"a", 1},
{"b", 1},
{"g", 1},
{"?", 1},
{"N-24G", 5},
{"N-5G", 4},
};
#define iwe_stream_add_event_rsl iwe_stream_add_event
#define MAX_CUSTOM_LEN 64
static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
struct ieee80211_network *network,
struct iw_request_info *info)
{
char custom[MAX_CUSTOM_LEN];
char proto_name[IFNAMSIZ];
char *pname = proto_name;
char *p;
struct iw_event iwe;
int i, j;
u16 max_rate, rate;
static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
/* First entry *MUST* be the AP MAC address */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
/* Remaining entries will be displayed in the order we provide them */
/* Add the ESSID */
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
// if (network->flags & NETWORK_EMPTY_ESSID) {
if (network->ssid_len == 0) {
iwe.u.data.length = sizeof("<hidden>");
start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
} else {
iwe.u.data.length = min(network->ssid_len, (u8)32);
start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
}
/* Add the protocol name */
iwe.cmd = SIOCGIWNAME;
for (i = 0; i < ARRAY_SIZE(ieee80211_modes); i++) {
if (network->mode & BIT(i)) {
sprintf(pname, ieee80211_modes[i].mode_string, ieee80211_modes[i].mode_size);
pname += ieee80211_modes[i].mode_size;
}
}
*pname = '\0';
snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
/* Add mode */
iwe.cmd = SIOCGIWMODE;
if (network->capability &
(WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
if (network->capability & WLAN_CAPABILITY_BSS)
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
}
/* Add frequency/channel */
iwe.cmd = SIOCGIWFREQ;
/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
iwe.u.freq.e = 3; */
iwe.u.freq.m = network->channel;
iwe.u.freq.e = 0;
iwe.u.freq.i = 0;
start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
/* Add encryption capability */
iwe.cmd = SIOCGIWENCODE;
if (network->capability & WLAN_CAPABILITY_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
/* Add basic and extended rates */
max_rate = 0;
p = custom;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
for (i = 0, j = 0; i < network->rates_len; ) {
if (j < network->rates_ex_len &&
((network->rates_ex[j] & 0x7F) <
(network->rates[i] & 0x7F)))
rate = network->rates_ex[j++] & 0x7F;
else
rate = network->rates[i++] & 0x7F;
if (rate > max_rate)
max_rate = rate;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
}
for (; j < network->rates_ex_len; j++) {
rate = network->rates_ex[j] & 0x7F;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
if (rate > max_rate)
max_rate = rate;
}
if (network->mode >= IEEE_N_24G) /* add N rate here */ {
struct ht_capability_ele *ht_cap = NULL;
bool is40M = false, isShortGI = false;
u8 max_mcs = 0;
if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[4];
else
ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[0];
is40M = (ht_cap->ChlWidth) ? 1 : 0;
isShortGI = (ht_cap->ChlWidth) ?
((ht_cap->ShortGI40Mhz) ? 1 : 0) :
((ht_cap->ShortGI20Mhz) ? 1 : 0);
max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
if (rate > max_rate)
max_rate = rate;
}
iwe.cmd = SIOCGIWRATE;
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
iwe.u.bitrate.value = max_rate * 500000;
start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
IW_EV_PARAM_LEN);
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
/* Add quality statistics */
/* TODO: Fix these values... */
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = network->stats.signal;
iwe.u.qual.level = network->stats.rssi;
iwe.u.qual.noise = network->stats.noise;
iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
iwe.u.qual.updated = 7;
start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
iwe.cmd = IWEVCUSTOM;
p = custom;
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
if (ieee->wpa_enabled && network->wpa_ie_len) {
char buf[MAX_WPA_IE_LEN * 2 + 30];
// printk("WPA IE\n");
u8 *p = buf;
p += sprintf(p, "wpa_ie=");
for (i = 0; i < network->wpa_ie_len; i++)
p += sprintf(p, "%02x", network->wpa_ie[i]);
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = strlen(buf);
start = iwe_stream_add_point(info, start, stop, &iwe, buf);
}
if (ieee->wpa_enabled && network->rsn_ie_len) {
char buf[MAX_WPA_IE_LEN * 2 + 30];
u8 *p = buf;
p += sprintf(p, "rsn_ie=");
for (i = 0; i < network->rsn_ie_len; i++)
p += sprintf(p, "%02x", network->rsn_ie[i]);
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = strlen(buf);
start = iwe_stream_add_point(info, start, stop, &iwe, buf);
}
/* Add EXTRA: Age to display seconds since last beacon/probe response
* for given network. */
iwe.cmd = IWEVCUSTOM;
p = custom;
p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
" Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
return start;
}
int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct ieee80211_network *network;
unsigned long flags;
char *ev = extra;
// char *stop = ev + IW_SCAN_MAX_DATA;
char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
//char *stop = ev + IW_SCAN_MAX_DATA;
int i = 0;
int err = 0;
IEEE80211_DEBUG_WX("Getting scan\n");
mutex_lock(&ieee->wx_mutex);
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {
i++;
if ((stop - ev) < 200) {
err = -E2BIG;
break;
}
if (ieee->scan_age == 0 ||
time_after(network->last_scanned + ieee->scan_age, jiffies))
ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
"%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
spin_unlock_irqrestore(&ieee->lock, flags);
mutex_unlock(&ieee->wx_mutex);
wrqu->data.length = ev - extra;
wrqu->data.flags = 0;
IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
return err;
}
EXPORT_SYMBOL(ieee80211_wx_get_scan);
int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
struct iw_point *erq = &(wrqu->encoding);
struct net_device *dev = ieee->dev;
struct ieee80211_security sec = {
.flags = 0
};
int i, key, key_provided, len;
struct ieee80211_crypt_data **crypt;
IEEE80211_DEBUG_WX("SET_ENCODE\n");
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
if (key > WEP_KEYS)
return -EINVAL;
key--;
key_provided = 1;
} else {
key_provided = 0;
key = ieee->tx_keyidx;
}
IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
"provided" : "default");
crypt = &ieee->crypt[key];
if (erq->flags & IW_ENCODE_DISABLED) {
if (key_provided && *crypt) {
IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
key);
ieee80211_crypt_delayed_deinit(ieee, crypt);
} else
IEEE80211_DEBUG_WX("Disabling encryption.\n");
/* Check all the keys to see if any are still configured,
* and if no key index was provided, de-init them all */
for (i = 0; i < WEP_KEYS; i++) {
if (ieee->crypt[i]) {
if (key_provided)
break;
ieee80211_crypt_delayed_deinit(
ieee, &ieee->crypt[i]);
}
}
if (i == WEP_KEYS) {
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_ENABLED | SEC_LEVEL;
}
goto done;
}
sec.enabled = 1;
sec.flags |= SEC_ENABLED;
if (*crypt && (*crypt)->ops &&
strcmp((*crypt)->ops->name, "WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm
* on this key */
ieee80211_crypt_delayed_deinit(ieee, crypt);
}
if (!*crypt) {
struct ieee80211_crypt_data *new_crypt;
/* take WEP into use */
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
GFP_KERNEL);
if (!new_crypt)
return -ENOMEM;
new_crypt->ops = try_then_request_module(ieee80211_get_crypto_ops("WEP"),
"ieee80211_crypt_wep");
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
kfree(new_crypt);
new_crypt = NULL;
netdev_warn(dev, "could not initialize WEP: "
"load module ieee80211_crypt_wep\n");
return -EOPNOTSUPP;
}
*crypt = new_crypt;
}
/* If a new key was provided, set it up */
if (erq->length > 0) {
len = erq->length <= 5 ? 5 : 13;
memcpy(sec.keys[key], keybuf, erq->length);
if (len > erq->length)
memset(sec.keys[key] + erq->length, 0,
len - erq->length);
IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
key, escape_essid(sec.keys[key], len),
erq->length, len);
sec.key_sizes[key] = len;
(*crypt)->ops->set_key(sec.keys[key], len, NULL,
(*crypt)->priv);
sec.flags |= BIT(key);
/* This ensures a key will be activated if no key is
* explicitly set
*/
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
ieee->tx_keyidx = key;
} else {
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
NULL, (*crypt)->priv);
if (len == 0) {
/* Set a default key of all 0 */
printk("Setting key %d to all zero.\n",
key);
IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
key);
memset(sec.keys[key], 0, 13);
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
(*crypt)->priv);
sec.key_sizes[key] = 13;
sec.flags |= BIT(key);
}
/* No key data - just set the default TX key index */
if (key_provided) {
IEEE80211_DEBUG_WX(
"Setting key %d to default Tx key.\n", key);
ieee->tx_keyidx = key;
sec.active_key = key;
sec.flags |= SEC_ACTIVE_KEY;
}
}
done:
ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
sec.flags |= SEC_AUTH_MODE;
IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
"OPEN" : "SHARED KEY");
/* For now we just support WEP, so only set that security level...
* TODO: When WPA is added this is one place that needs to change */
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
if (ieee->set_security)
ieee->set_security(dev, &sec);
/* Do not reset port if card is in Managed mode since resetting will
* generate new IEEE 802.11 authentication which may end up in looping
* with IEEE 802.1X. If your hardware requires a reset after WEP
* configuration (for example... Prism2), implement the reset_port in
* the callbacks structures used to initialize the 802.11 stack. */
if (ieee->reset_on_keychange &&
ieee->iw_mode != IW_MODE_INFRA &&
ieee->reset_port && ieee->reset_port(dev)) {
netdev_dbg(ieee->dev, "reset_port failed\n");
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_encode);
int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
struct iw_point *erq = &(wrqu->encoding);
int len, key;
struct ieee80211_crypt_data *crypt;
IEEE80211_DEBUG_WX("GET_ENCODE\n");
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
if (key > WEP_KEYS)
return -EINVAL;
key--;
} else
key = ieee->tx_keyidx;
crypt = ieee->crypt[key];
erq->flags = key + 1;
if (!crypt || !crypt->ops) {
erq->length = 0;
erq->flags |= IW_ENCODE_DISABLED;
return 0;
}
len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
if (len < 0)
len = 0;
erq->length = len;
erq->flags |= IW_ENCODE_ENABLED;
if (ieee->open_wep)
erq->flags |= IW_ENCODE_OPEN;
else
erq->flags |= IW_ENCODE_RESTRICTED;
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_encode);
int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
struct net_device *dev = ieee->dev;
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int i, idx;
int group_key = 0;
const char *alg, *module;
struct ieee80211_crypto_ops *ops;
struct ieee80211_crypt_data **crypt;
struct ieee80211_security sec = {
.flags = 0,
};
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
if (idx < 1 || idx > WEP_KEYS)
return -EINVAL;
idx--;
} else
idx = ieee->tx_keyidx;
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
crypt = &ieee->crypt[idx];
group_key = 1;
} else {
/* some Cisco APs use idx>0 for unicast in dynamic WEP */
if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
return -EINVAL;
if (ieee->iw_mode == IW_MODE_INFRA)
crypt = &ieee->crypt[idx];
else
return -EINVAL;
}
sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
if ((encoding->flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE) {
if (*crypt)
ieee80211_crypt_delayed_deinit(ieee, crypt);
for (i = 0; i < WEP_KEYS; i++)
if (ieee->crypt[i])
break;
if (i == WEP_KEYS) {
sec.enabled = 0;
// sec.encrypt = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_LEVEL;
}
goto done;
}
sec.enabled = 1;
// sec.encrypt = 1;
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
module = "ieee80211_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
module = "ieee80211_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
module = "ieee80211_crypt_ccmp";
break;
default:
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
ret = -EINVAL;
goto done;
}
printk("alg name:%s\n", alg);
ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module);
if (!ops) {
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
printk("========>unknown crypto alg %d\n", ext->alg);
ret = -EINVAL;
goto done;
}
if (!*crypt || (*crypt)->ops != ops) {
struct ieee80211_crypt_data *new_crypt;
ieee80211_crypt_delayed_deinit(ieee, crypt);
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
if (!new_crypt) {
ret = -ENOMEM;
goto done;
}
new_crypt->ops = ops;
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(idx);
if (!new_crypt->priv) {
kfree(new_crypt);
ret = -EINVAL;
goto done;
}
*crypt = new_crypt;
}
if (ext->key_len > 0 && (*crypt)->ops->set_key &&
(*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
(*crypt)->priv) < 0) {
IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
printk("key setting failed\n");
ret = -EINVAL;
goto done;
}
//skip_host_crypt:
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
ieee->tx_keyidx = idx;
sec.active_key = idx;
sec.flags |= SEC_ACTIVE_KEY;
}
if (ext->alg != IW_ENCODE_ALG_NONE) {
//memcpy(sec.keys[idx], ext->key, ext->key_len);
sec.key_sizes[idx] = ext->key_len;
sec.flags |= BIT(idx);
if (ext->alg == IW_ENCODE_ALG_WEP) {
// sec.encode_alg[idx] = SEC_ALG_WEP;
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1;
} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
// sec.encode_alg[idx] = SEC_ALG_TKIP;
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_2;
} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
// sec.encode_alg[idx] = SEC_ALG_CCMP;
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_3;
}
/* Don't set sec level for group keys. */
if (group_key)
sec.flags &= ~SEC_LEVEL;
}
done:
if (ieee->set_security)
ieee->set_security(ieee->dev, &sec);
if (ieee->reset_on_keychange &&
ieee->iw_mode != IW_MODE_INFRA &&
ieee->reset_port && ieee->reset_port(dev)) {
IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
return -EINVAL;
}
return ret;
}
EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
struct ieee80211_crypt_data *crypt;
int idx, max_key_len;
max_key_len = encoding->length - sizeof(*ext);
if (max_key_len < 0)
return -EINVAL;
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
if (idx < 1 || idx > WEP_KEYS)
return -EINVAL;
idx--;
} else
idx = ieee->tx_keyidx;
if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
ext->alg != IW_ENCODE_ALG_WEP)
if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
return -EINVAL;
crypt = ieee->crypt[idx];
encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext));
if (!crypt || !crypt->ops) {
ext->alg = IW_ENCODE_ALG_NONE;
ext->key_len = 0;
encoding->flags |= IW_ENCODE_DISABLED;
} else {
if (strcmp(crypt->ops->name, "WEP") == 0)
ext->alg = IW_ENCODE_ALG_WEP;
else if (strcmp(crypt->ops->name, "TKIP") == 0)
ext->alg = IW_ENCODE_ALG_TKIP;
else if (strcmp(crypt->ops->name, "CCMP") == 0)
ext->alg = IW_ENCODE_ALG_CCMP;
else
return -EINVAL;
ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
encoding->flags |= IW_ENCODE_ENABLED;
if (ext->key_len &&
(ext->alg == IW_ENCODE_ALG_TKIP ||
ext->alg == IW_ENCODE_ALG_CCMP))
ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct iw_mlme *mlme = (struct iw_mlme *)extra;
switch (mlme->cmd) {
case IW_MLME_DEAUTH:
case IW_MLME_DISASSOC:
ieee80211_disassociate(ieee);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_mlme);
int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
struct iw_request_info *info,
struct iw_param *data, char *extra)
{
switch (data->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
/*need to support wpa2 here*/
break;
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT:
/*
* * Host AP driver does not use these parameters and allows
* * wpa_supplicant to control them internally.
* */
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
ieee->tkip_countermeasures = data->value;
break;
case IW_AUTH_DROP_UNENCRYPTED:
ieee->drop_unencrypted = data->value;
break;
case IW_AUTH_80211_AUTH_ALG:
//printk("======>%s():data->value is %d\n",__func__,data->value);
// ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
if (data->value & IW_AUTH_ALG_SHARED_KEY) {
ieee->open_wep = 0;
ieee->auth_mode = 1;
} else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
ieee->open_wep = 1;
ieee->auth_mode = 0;
} else if (data->value & IW_AUTH_ALG_LEAP) {
ieee->open_wep = 1;
ieee->auth_mode = 2;
} else
return -EINVAL;
break;
case IW_AUTH_WPA_ENABLED:
ieee->wpa_enabled = (data->value) ? 1 : 0;
break;
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
ieee->ieee802_1x = data->value;
break;
case IW_AUTH_PRIVACY_INVOKED:
ieee->privacy_invoked = data->value;
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_auth);
int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
{
u8 *buf;
if (len > MAX_WPA_IE_LEN || (len && !ie)) {
//printk("return error out, len:%d\n", len);
return -EINVAL;
}
if (len) {
if (len != ie[1] + 2) {
printk("len:%zu, ie:%d\n", len, ie[1]);
return -EINVAL;
}
buf = kmemdup(ie, len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = len;
} else {
kfree(ieee->wpa_ie);
ieee->wpa_ie = NULL;
ieee->wpa_ie_len = 0;
}
return 0;
}
EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);

View File

@ -1,54 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BATYPE_H_
#define _BATYPE_H_
#define BA_SETUP_TIMEOUT 200
#define BA_POLICY_DELAYED 0
#define BA_POLICY_IMMEDIATE 1
#define ADDBA_STATUS_SUCCESS 0
#define ADDBA_STATUS_REFUSED 37
#define ADDBA_STATUS_INVALID_PARAM 38
#define DELBA_REASON_END_BA 37
#define DELBA_REASON_UNKNOWN_BA 38
#define DELBA_REASON_TIMEOUT 39
union sequence_control {
u16 short_data;
struct {
u16 frag_num:4;
u16 seq_num:12;
} field;
};
union ba_param_set {
u16 short_data;
struct {
u16 amsdu_support:1;
u16 ba_policy:1;
u16 tid:4;
u16 buffer_size:10;
} field;
};
union delba_param_set {
u16 short_data;
struct {
u16 reserved:11;
u16 initiator:1;
u16 tid:4;
} field;
};
struct ba_record {
struct timer_list timer;
u8 valid;
u8 dialog_token;
union ba_param_set param_set;
u16 timeout_value;
union sequence_control start_seq_ctrl;
};
#endif //end _BATYPE_H_

View File

@ -1,700 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/********************************************************************************************************************************
* This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
* related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send
* ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
* WB 2008-05-27
* *****************************************************************************************************************************/
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include "ieee80211.h"
#include "rtl819x_BA.h"
/********************************************************************************************************************
*function: Activate BA entry. And if Time is nozero, start timer.
* input: struct ba_record *pBA //BA entry to be enabled
* u16 Time //indicate time delay.
* output: none
********************************************************************************************************************/
static void ActivateBAEntry(struct ieee80211_device *ieee, struct ba_record *pBA, u16 Time)
{
pBA->valid = true;
if (Time != 0)
mod_timer(&pBA->timer, jiffies + msecs_to_jiffies(Time));
}
/********************************************************************************************************************
*function: deactivate BA entry, including its timer.
* input: struct ba_record *pBA //BA entry to be disabled
* output: none
********************************************************************************************************************/
static void DeActivateBAEntry(struct ieee80211_device *ieee, struct ba_record *pBA)
{
pBA->valid = false;
del_timer_sync(&pBA->timer);
}
/********************************************************************************************************************
*function: deactivete BA entry in Tx Ts, and send DELBA.
* input:
* struct tx_ts_record *pTxTs //Tx Ts which is to deactivate BA entry.
* output: none
* notice: As struct tx_ts_record * structure will be defined in QOS, so wait to be merged. //FIXME
********************************************************************************************************************/
static u8 TxTsDeleteBA(struct ieee80211_device *ieee, struct tx_ts_record *pTxTs)
{
struct ba_record *pAdmittedBa = &pTxTs->tx_admitted_ba_record; //These two BA entries must exist in TS structure
struct ba_record *pPendingBa = &pTxTs->tx_pending_ba_record;
u8 bSendDELBA = false;
// Delete pending BA
if (pPendingBa->valid) {
DeActivateBAEntry(ieee, pPendingBa);
bSendDELBA = true;
}
// Delete admitted BA
if (pAdmittedBa->valid) {
DeActivateBAEntry(ieee, pAdmittedBa);
bSendDELBA = true;
}
return bSendDELBA;
}
/********************************************************************************************************************
*function: deactivete BA entry in Tx Ts, and send DELBA.
* input:
* struct rx_ts_record *pRxTs //Rx Ts which is to deactivate BA entry.
* output: none
* notice: As struct rx_ts_record * structure will be defined in QOS, so wait to be merged. //FIXME, same with above
********************************************************************************************************************/
static u8 RxTsDeleteBA(struct ieee80211_device *ieee, struct rx_ts_record *pRxTs)
{
struct ba_record *pBa = &pRxTs->rx_admitted_ba_record;
u8 bSendDELBA = false;
if (pBa->valid) {
DeActivateBAEntry(ieee, pBa);
bSendDELBA = true;
}
return bSendDELBA;
}
/********************************************************************************************************************
*function: reset BA entry
* input:
* struct ba_record *pBA //entry to be reset
* output: none
********************************************************************************************************************/
void ResetBaEntry(struct ba_record *pBA)
{
pBA->valid = false;
pBA->param_set.short_data = 0;
pBA->timeout_value = 0;
pBA->dialog_token = 0;
pBA->start_seq_ctrl.short_data = 0;
}
//These functions need porting here or not?
/*******************************************************************************************************************************
*function: construct ADDBAREQ and ADDBARSP frame here together.
* input: u8* Dst //ADDBA frame's destination
* struct ba_record *pBA //BA_RECORD entry which stores the necessary information for BA.
* u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
* u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
* output: none
* return: sk_buff* skb //return constructed skb to xmit
*******************************************************************************************************************************/
static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, struct ba_record *pBA, u16 StatusCode, u8 type)
{
struct sk_buff *skb = NULL;
struct rtl_80211_hdr_3addr *BAReq = NULL;
u8 *tag = NULL;
u16 len = ieee->tx_headroom + 9;
//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev);
if (pBA == NULL) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n");
return NULL;
}
skb = dev_alloc_skb(len + sizeof(struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
if (!skb)
return NULL;
memset(skb->data, 0, sizeof(struct rtl_80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
skb_reserve(skb, ieee->tx_headroom);
BAReq = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
memcpy(BAReq->addr1, Dst, ETH_ALEN);
memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
//tag += sizeof( struct rtl_80211_hdr_3addr); //move to action field
tag = skb_put(skb, 9);
*tag++ = ACT_CAT_BA;
*tag++ = type;
// Dialog Token
*tag++ = pBA->dialog_token;
if (type == ACT_ADDBARSP) {
// Status Code
netdev_info(ieee->dev, "=====>to send ADDBARSP\n");
put_unaligned_le16(StatusCode, tag);
tag += 2;
}
// BA Parameter Set
put_unaligned_le16(pBA->param_set.short_data, tag);
tag += 2;
// BA Timeout Value
put_unaligned_le16(pBA->timeout_value, tag);
tag += 2;
if (type == ACT_ADDBAREQ) {
// BA Start SeqCtrl
memcpy(tag, (u8 *)&(pBA->start_seq_ctrl), 2);
tag += 2;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
return skb;
//return NULL;
}
/********************************************************************************************************************
*function: construct DELBA frame
* input: u8* dst //DELBA frame's destination
* struct ba_record *pBA //BA_RECORD entry which stores the necessary information for BA
* enum tr_select TxRxSelect //TX RX direction
* u16 ReasonCode //status code.
* output: none
* return: sk_buff* skb //return constructed skb to xmit
********************************************************************************************************************/
static struct sk_buff *ieee80211_DELBA(
struct ieee80211_device *ieee,
u8 *dst,
struct ba_record *pBA,
enum tr_select TxRxSelect,
u16 ReasonCode
)
{
union delba_param_set DelbaParamSet;
struct sk_buff *skb = NULL;
struct rtl_80211_hdr_3addr *Delba = NULL;
u8 *tag = NULL;
//len = head len + DELBA Parameter Set(2) + Reason Code(2)
u16 len = 6 + ieee->tx_headroom;
if (net_ratelimit())
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
"========>%s(), ReasonCode(%d) sentd to:%pM\n",
__func__, ReasonCode, dst);
memset(&DelbaParamSet, 0, 2);
DelbaParamSet.field.initiator = (TxRxSelect == TX_DIR) ? 1 : 0;
DelbaParamSet.field.tid = pBA->param_set.field.tid;
skb = dev_alloc_skb(len + sizeof(struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
if (!skb)
return NULL;
// memset(skb->data, 0, len+sizeof( struct rtl_80211_hdr_3addr));
skb_reserve(skb, ieee->tx_headroom);
Delba = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
memcpy(Delba->addr1, dst, ETH_ALEN);
memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
tag = skb_put(skb, 6);
*tag++ = ACT_CAT_BA;
*tag++ = ACT_DELBA;
// DELBA Parameter Set
put_unaligned_le16(DelbaParamSet.short_data, tag);
tag += 2;
// Reason Code
put_unaligned_le16(ReasonCode, tag);
tag += 2;
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
if (net_ratelimit())
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
"<=====%s()\n", __func__);
return skb;
}
/********************************************************************************************************************
*function: send ADDBAReq frame out
* input: u8* dst //ADDBAReq frame's destination
* struct ba_record *pBA //BA_RECORD entry which stores the necessary information for BA
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee,
u8 *dst, struct ba_record *pBA)
{
struct sk_buff *skb;
skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
if (skb) {
softmac_mgmt_xmit(skb, ieee);
//add statistic needed here.
//and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
//WB
} else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
}
}
/********************************************************************************************************************
*function: send ADDBARSP frame out
* input: u8* dst //DELBA frame's destination
* struct ba_record *pBA //BA_RECORD entry which stores the necessary information for BA
* u16 StatusCode //RSP StatusCode
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst,
struct ba_record *pBA, u16 StatusCode)
{
struct sk_buff *skb;
skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
if (skb) {
softmac_mgmt_xmit(skb, ieee);
//same above
} else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
}
return;
}
/********************************************************************************************************************
*function: send ADDBARSP frame out
* input: u8* dst //DELBA frame's destination
* struct ba_record *pBA //BA_RECORD entry which stores the necessary information for BA
* enum tr_select TxRxSelect //TX or RX
* u16 ReasonCode //DEL ReasonCode
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
static void ieee80211_send_DELBA(struct ieee80211_device *ieee, u8 *dst,
struct ba_record *pBA, enum tr_select TxRxSelect,
u16 ReasonCode)
{
struct sk_buff *skb;
skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
if (skb) {
softmac_mgmt_xmit(skb, ieee);
//same above
} else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
}
}
/********************************************************************************************************************
*function: RX ADDBAReq
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
{
struct rtl_80211_hdr_3addr *req = NULL;
u16 rc = 0;
u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
struct ba_record *pBA = NULL;
union ba_param_set *pBaParamSet = NULL;
u16 *pBaTimeoutVal = NULL;
union sequence_control *pBaStartSeqCtrl = NULL;
struct rx_ts_record *pTS = NULL;
if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
IEEE80211_DEBUG(IEEE80211_DL_ERR,
" Invalid skb len in BAREQ(%d / %zu)\n",
skb->len,
(sizeof(struct rtl_80211_hdr_3addr) + 9));
return -1;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
req = (struct rtl_80211_hdr_3addr *)skb->data;
tag = (u8 *)req;
dst = &req->addr2[0];
tag += sizeof(struct rtl_80211_hdr_3addr);
pDialogToken = tag + 2; //category+action
pBaParamSet = (union ba_param_set *)(tag + 3); //+DialogToken
pBaTimeoutVal = (u16 *)(tag + 5);
pBaStartSeqCtrl = (union sequence_control *)(req + 7);
netdev_info(ieee->dev, "====================>rx ADDBAREQ from :%pM\n", dst);
//some other capability is not ready now.
if ((ieee->current_network.qos_data.active == 0) ||
(!ieee->pHTInfo->bCurrentHTSupport)) //||
// (!ieee->pStaQos->bEnableRxImmBA) )
{
rc = ADDBA_STATUS_REFUSED;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
goto OnADDBAReq_Fail;
}
// Search for related traffic stream.
// If there is no matched TS, reject the ADDBA request.
if (!GetTs(
ieee,
(struct ts_common_info **)(&pTS),
dst,
(u8)(pBaParamSet->field.tid),
RX_DIR,
true)) {
rc = ADDBA_STATUS_REFUSED;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
goto OnADDBAReq_Fail;
}
pBA = &pTS->rx_admitted_ba_record;
// To Determine the ADDBA Req content
// We can do much more check here, including buffer_size, AMSDU_Support, Policy, StartSeqCtrl...
// I want to check StartSeqCtrl to make sure when we start aggregation!!!
//
if (pBaParamSet->field.ba_policy == BA_POLICY_DELAYED) {
rc = ADDBA_STATUS_INVALID_PARAM;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
goto OnADDBAReq_Fail;
}
// Admit the ADDBA Request
//
DeActivateBAEntry(ieee, pBA);
pBA->dialog_token = *pDialogToken;
pBA->param_set = *pBaParamSet;
pBA->timeout_value = *pBaTimeoutVal;
pBA->start_seq_ctrl = *pBaStartSeqCtrl;
//for half N mode we only aggregate 1 frame
if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
pBA->param_set.field.buffer_size = 1;
else
pBA->param_set.field.buffer_size = 32;
ActivateBAEntry(ieee, pBA, pBA->timeout_value);
ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
// End of procedure.
return 0;
OnADDBAReq_Fail:
{
struct ba_record BA;
BA.param_set = *pBaParamSet;
BA.timeout_value = *pBaTimeoutVal;
BA.dialog_token = *pDialogToken;
BA.param_set.field.ba_policy = BA_POLICY_IMMEDIATE;
ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
return 0; //we send RSP out.
}
}
/********************************************************************************************************************
*function: RX ADDBARSP
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
{
struct rtl_80211_hdr_3addr *rsp = NULL;
struct ba_record *pPendingBA, *pAdmittedBA;
struct tx_ts_record *pTS = NULL;
u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
union ba_param_set *pBaParamSet = NULL;
u16 ReasonCode;
if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
IEEE80211_DEBUG(IEEE80211_DL_ERR,
" Invalid skb len in BARSP(%d / %zu)\n",
skb->len,
(sizeof(struct rtl_80211_hdr_3addr) + 9));
return -1;
}
rsp = (struct rtl_80211_hdr_3addr *)skb->data;
tag = (u8 *)rsp;
dst = &rsp->addr2[0];
tag += sizeof(struct rtl_80211_hdr_3addr);
pDialogToken = tag + 2;
pStatusCode = (u16 *)(tag + 3);
pBaParamSet = (union ba_param_set *)(tag + 5);
pBaTimeoutVal = (u16 *)(tag + 7);
// Check the capability
// Since we can always receive A-MPDU, we just check if it is under HT mode.
if (ieee->current_network.qos_data.active == 0 ||
!ieee->pHTInfo->bCurrentHTSupport ||
!ieee->pHTInfo->bCurrentAMPDUEnable) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
}
//
// Search for related TS.
// If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
//
if (!GetTs(
ieee,
(struct ts_common_info **)(&pTS),
dst,
(u8)(pBaParamSet->field.tid),
TX_DIR,
false)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
}
pTS->add_ba_req_in_progress = false;
pPendingBA = &pTS->tx_pending_ba_record;
pAdmittedBA = &pTS->tx_admitted_ba_record;
//
// Check if related BA is waiting for setup.
// If not, reject by sending DELBA frame.
//
if (pAdmittedBA->valid) {
// Since BA is already setup, we ignore all other ADDBA Response.
IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
return -1;
} else if ((!pPendingBA->valid) || (*pDialogToken != pPendingBA->dialog_token)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
} else {
IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
DeActivateBAEntry(ieee, pPendingBA);
}
if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
//
// Determine ADDBA Rsp content here.
// We can compare the value of BA parameter set that Peer returned and Self sent.
// If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
//
if (pBaParamSet->field.ba_policy == BA_POLICY_DELAYED) {
// Since this is a kind of ADDBA failed, we delay next ADDBA process.
pTS->add_ba_req_delayed = true;
DeActivateBAEntry(ieee, pAdmittedBA);
ReasonCode = DELBA_REASON_END_BA;
goto OnADDBARsp_Reject;
}
//
// Admitted condition
//
pAdmittedBA->dialog_token = *pDialogToken;
pAdmittedBA->timeout_value = *pBaTimeoutVal;
pAdmittedBA->start_seq_ctrl = pPendingBA->start_seq_ctrl;
pAdmittedBA->param_set = *pBaParamSet;
DeActivateBAEntry(ieee, pAdmittedBA);
ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
} else {
// Delay next ADDBA process.
pTS->add_ba_req_delayed = true;
}
// End of procedure
return 0;
OnADDBARsp_Reject:
{
struct ba_record BA;
BA.param_set = *pBaParamSet;
ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
return 0;
}
}
/********************************************************************************************************************
*function: RX DELBA
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
{
struct rtl_80211_hdr_3addr *delba = NULL;
union delba_param_set *pDelBaParamSet = NULL;
u8 *dst = NULL;
if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
IEEE80211_DEBUG(IEEE80211_DL_ERR,
" Invalid skb len in DELBA(%d / %zu)\n",
skb->len,
(sizeof(struct rtl_80211_hdr_3addr) + 6));
return -1;
}
if (ieee->current_network.qos_data.active == 0 ||
!ieee->pHTInfo->bCurrentHTSupport) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
return -1;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
delba = (struct rtl_80211_hdr_3addr *)skb->data;
dst = &delba->addr2[0];
pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
if (pDelBaParamSet->field.initiator == 1) {
struct rx_ts_record *pRxTs;
if (!GetTs(
ieee,
(struct ts_common_info **)&pRxTs,
dst,
(u8)pDelBaParamSet->field.tid,
RX_DIR,
false)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __func__);
return -1;
}
RxTsDeleteBA(ieee, pRxTs);
} else {
struct tx_ts_record *pTxTs;
if (!GetTs(
ieee,
(struct ts_common_info **)&pTxTs,
dst,
(u8)pDelBaParamSet->field.tid,
TX_DIR,
false)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __func__);
return -1;
}
pTxTs->using_ba = false;
pTxTs->add_ba_req_in_progress = false;
pTxTs->add_ba_req_delayed = false;
del_timer_sync(&pTxTs->ts_add_ba_timer);
//PlatformCancelTimer(Adapter, &pTxTs->ts_add_ba_timer);
TxTsDeleteBA(ieee, pTxTs);
}
return 0;
}
//
// ADDBA initiate. This can only be called by TX side.
//
void
TsInitAddBA(
struct ieee80211_device *ieee,
struct tx_ts_record *pTS,
u8 Policy,
u8 bOverwritePending
)
{
struct ba_record *pBA = &pTS->tx_pending_ba_record;
if (pBA->valid && !bOverwritePending)
return;
// Set parameters to "Pending" variable set
DeActivateBAEntry(ieee, pBA);
pBA->dialog_token++; // DialogToken: Only keep the latest dialog token
pBA->param_set.field.amsdu_support = 0; // Do not support A-MSDU with A-MPDU now!!
pBA->param_set.field.ba_policy = Policy; // Policy: Delayed or Immediate
pBA->param_set.field.tid = pTS->ts_common_info.t_spec.ts_info.uc_tsid; // TID
// buffer_size: This need to be set according to A-MPDU vector
pBA->param_set.field.buffer_size = 32; // buffer_size: This need to be set according to A-MPDU vector
pBA->timeout_value = 0; // Timeout value: Set 0 to disable Timer
pBA->start_seq_ctrl.field.seq_num = (pTS->tx_cur_seq + 3) % 4096; // Block Ack will start after 3 packets later.
ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
ieee80211_send_ADDBAReq(ieee, pTS->ts_common_info.addr, pBA);
}
void
TsInitDelBA(struct ieee80211_device *ieee, struct ts_common_info *pTsCommonInfo, enum tr_select TxRxSelect)
{
if (TxRxSelect == TX_DIR) {
struct tx_ts_record *pTxTs = (struct tx_ts_record *)pTsCommonInfo;
if (TxTsDeleteBA(ieee, pTxTs))
ieee80211_send_DELBA(
ieee,
pTsCommonInfo->addr,
(pTxTs->tx_admitted_ba_record.valid) ? (&pTxTs->tx_admitted_ba_record) : (&pTxTs->tx_pending_ba_record),
TxRxSelect,
DELBA_REASON_END_BA);
} else if (TxRxSelect == RX_DIR) {
struct rx_ts_record *pRxTs = (struct rx_ts_record *)pTsCommonInfo;
if (RxTsDeleteBA(ieee, pRxTs))
ieee80211_send_DELBA(
ieee,
pTsCommonInfo->addr,
&pRxTs->rx_admitted_ba_record,
TxRxSelect,
DELBA_REASON_END_BA);
}
}
/********************************************************************************************************************
*function: BA setup timer
* input: unsigned long data //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
* return: NULL
* notice:
********************************************************************************************************************/
void BaSetupTimeOut(struct timer_list *t)
{
struct tx_ts_record *pTxTs = from_timer(pTxTs, t, tx_pending_ba_record.timer);
pTxTs->add_ba_req_in_progress = false;
pTxTs->add_ba_req_delayed = true;
pTxTs->tx_pending_ba_record.valid = false;
}
void TxBaInactTimeout(struct timer_list *t)
{
struct tx_ts_record *pTxTs = from_timer(pTxTs, t, tx_admitted_ba_record.timer);
struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
TxTsDeleteBA(ieee, pTxTs);
ieee80211_send_DELBA(
ieee,
pTxTs->ts_common_info.addr,
&pTxTs->tx_admitted_ba_record,
TX_DIR,
DELBA_REASON_TIMEOUT);
}
void RxBaInactTimeout(struct timer_list *t)
{
struct rx_ts_record *pRxTs = from_timer(pRxTs, t, rx_admitted_ba_record.timer);
struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
RxTsDeleteBA(ieee, pRxTs);
ieee80211_send_DELBA(
ieee,
pRxTs->ts_common_info.addr,
&pRxTs->rx_admitted_ba_record,
RX_DIR,
DELBA_REASON_TIMEOUT);
}

View File

@ -1,302 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RTL819XU_HTTYPE_H_
#define _RTL819XU_HTTYPE_H_
/*
* The HT Capability element is present in beacons, association request,
* reassociation request and probe response frames
*/
/*
* MIMO Power Save Settings
*/
#define MIMO_PS_STATIC 0
/*
* There should be 128 bits to cover all of the MCS rates. However, since
* 8190 does not support too much rates, one integer is quite enough.
*/
#define HTCLNG 4
/*
* Represent Channel Width in HT Capabilities
*/
enum ht_channel_width {
HT_CHANNEL_WIDTH_20 = 0,
HT_CHANNEL_WIDTH_20_40 = 1,
};
/*
* Represent Extension Channel Offset in HT Capabilities
* This is available only in 40Mhz mode.
*/
enum ht_extension_chan_offset {
HT_EXTCHNL_OFFSET_NO_EXT = 0,
HT_EXTCHNL_OFFSET_UPPER = 1,
HT_EXTCHNL_OFFSET_NO_DEF = 2,
HT_EXTCHNL_OFFSET_LOWER = 3,
};
struct ht_capability_ele {
//HT capability info
u8 AdvCoding:1;
u8 ChlWidth:1;
u8 MimoPwrSave:2;
u8 GreenField:1;
u8 ShortGI20Mhz:1;
u8 ShortGI40Mhz:1;
u8 TxSTBC:1;
u8 RxSTBC:2;
u8 DelayBA:1;
u8 MaxAMSDUSize:1;
u8 DssCCk:1;
u8 PSMP:1;
u8 Rsvd1:1;
u8 LSigTxopProtect:1;
//MAC HT parameters info
u8 MaxRxAMPDUFactor:2;
u8 MPDUDensity:3;
u8 Rsvd2:3;
//Supported MCS set
u8 MCS[16];
//Extended HT Capability Info
u16 ExtHTCapInfo;
//TXBF Capabilities
u8 TxBFCap[4];
//Antenna Selection Capabilities
u8 ASCap;
} __packed;
/*
* The HT Information element is present in beacons
* Only AP is required to include this element
*/
typedef struct _HT_INFORMATION_ELE {
u8 ControlChl;
u8 ExtChlOffset:2;
u8 RecommemdedTxWidth:1;
u8 RIFS:1;
u8 PSMPAccessOnly:1;
u8 SrvIntGranularity:3;
u8 OptMode:2;
u8 NonGFDevPresent:1;
u8 Revd1:5;
u8 Revd2:8;
u8 Rsvd3:6;
u8 DualBeacon:1;
u8 DualCTSProtect:1;
u8 SecondaryBeacon:1;
u8 LSigTxopProtectFull:1;
u8 PcoActive:1;
u8 PcoPhase:1;
u8 Rsvd4:4;
u8 BasicMSC[16];
} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
typedef enum _HT_SPEC_VER {
HT_SPEC_VER_IEEE = 0,
HT_SPEC_VER_EWC = 1,
} HT_SPEC_VER, *PHT_SPEC_VER;
typedef enum _HT_AGGRE_MODE_E {
HT_AGG_AUTO = 0,
HT_AGG_FORCE_ENABLE = 1,
HT_AGG_FORCE_DISABLE = 2,
} HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
/*
* The Data structure is used to keep HT related variables when card is
* configured as non-AP STA mode. **Note** Current_xxx should be set
* to default value in HTInitializeHTInfo()
*/
typedef struct _RT_HIGH_THROUGHPUT {
u8 bEnableHT;
u8 bCurrentHTSupport;
u8 bRegBW40MHz; // Tx 40MHz channel capability
u8 bCurBW40MHz; // Tx 40MHz channel capability
u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
u8 bCurShortGI40MHz; // Tx Short GI for 40MHz
u8 bRegShortGI20MHz; // Tx Short GI for 20MHz
u8 bCurShortGI20MHz; // Tx Short GI for 20MHz
u8 bRegSuppCCK; // Tx CCK rate capability
u8 bCurSuppCCK; // Tx CCK rate capability
// 802.11n spec version for "peer"
HT_SPEC_VER ePeerHTSpecVer;
// HT related information for "Self"
struct ht_capability_ele SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
// HT related information for "Peer"
u8 PeerHTCapBuf[32];
u8 PeerHTInfoBuf[32];
// A-MSDU related
u8 bAMSDU_Support; // This indicates Tx A-MSDU capability
u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability
u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability
u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability
// AMPDU related <2006.08.10 Emily>
u8 bAMPDUEnable; // This indicate Tx A-MPDU capability
u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability
u8 AMPDU_Factor; // This indicate Tx A-MPDU capability
u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability
u8 MPDU_Density; // This indicate Tx A-MPDU capability
u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability
// Forced A-MPDU enable
HT_AGGRE_MODE_E ForcedAMPDUMode;
u8 ForcedAMPDUFactor;
u8 ForcedMPDUDensity;
// Forced A-MSDU enable
HT_AGGRE_MODE_E ForcedAMSDUMode;
u16 ForcedAMSDUMaxSize;
u8 bForcedShortGI;
u8 CurrentOpMode;
// MIMO PS related
u8 SelfMimoPs;
u8 PeerMimoPs;
// 40MHz Channel Offset settings.
enum ht_extension_chan_offset CurSTAExtChnlOffset;
u8 bCurTxBW40MHz; // If we use 40 MHz to Tx
u8 PeerBandwidth;
// For Bandwidth Switching
u8 bSwBwInProgress;
u8 SwBwStep;
//struct timer_list SwBwTimer; //moved to ieee80211_device. as timer_list need include some header file here.
// For Realtek proprietary A-MPDU factor for aggregation
u8 bRegRT2RTAggregation;
u8 bCurrentRT2RTAggregation;
u8 bCurrentRT2RTLongSlotTime;
u8 szRT2RTAggBuffer[10];
// Rx Reorder control
u8 bRegRxReorderEnable;
u8 bCurRxReorderEnable;
u8 RxReorderWinSize;
u8 RxReorderPendingTime;
u16 RxReorderDropCounter;
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
u8 UsbTxAggrNum;
#endif
#ifdef USB_RX_AGGREGATION_SUPPORT
u8 UsbRxFwAggrEn;
u8 UsbRxFwAggrPageNum;
u8 UsbRxFwAggrPacketNum;
u8 UsbRxFwAggrTimeout;
#endif
// Add for Broadcom(Linksys) IOT. Joseph
u8 bIsPeerBcm;
// For IOT issue.
u8 IOTPeer;
u32 IOTAction;
} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
/*
* The Data structure is used to keep HT related variable for "each AP"
* when card is configured as "STA mode"
*/
typedef struct _BSS_HT {
u8 bdSupportHT;
// HT related elements
u8 bdHTCapBuf[32];
u16 bdHTCapLen;
u8 bdHTInfoBuf[32];
u16 bdHTInfoLen;
HT_SPEC_VER bdHTSpecVer;
//struct ht_capability_ele bdHTCapEle;
//HT_INFORMATION_ELE bdHTInfoEle;
u8 bdRT2RTAggregation;
u8 bdRT2RTLongSlotTime;
} __attribute__ ((packed)) BSS_HT, *PBSS_HT;
extern u8 MCS_FILTER_ALL[16];
extern u8 MCS_FILTER_1SS[16];
/*
* 2007/07/11 MH Modify the macro. Becaus STA may link with a N-AP. If we set
* STA in A/B/G mode and AP is still in N mode. The macro will be wrong. We have
* to add a macro to judge wireless mode.
*/
#define PICK_RATE(_nLegacyRate, _nMcsRate) \
(_nMcsRate == 0) ? (_nLegacyRate & 0x7f) : (_nMcsRate)
/* 2007/07/12 MH We only define legacy and HT wireless mode now. */
#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK
#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \
((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ? \
(LegacyRate) : \
(PICK_RATE(LegacyRate, HTRate))
// MCS Bw 40 {1~7, 12~15,32}
#define RATE_ADPT_1SS_MASK 0xFF
#define RATE_ADPT_2SS_MASK 0xF0 //Skip MCS8~11 because mcs7 > mcs6, 9, 10, 11. 2007.01.16 by Emily
#define RATE_ADPT_MCS32_MASK 0x01
#define IS_11N_MCS_RATE(rate) (rate & 0x80)
typedef enum _HT_AGGRE_SIZE {
HT_AGG_SIZE_8K = 0,
HT_AGG_SIZE_16K = 1,
HT_AGG_SIZE_32K = 2,
HT_AGG_SIZE_64K = 3,
} HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E;
/* Indicate different AP vendor for IOT issue */
typedef enum _HT_IOT_PEER {
HT_IOT_PEER_UNKNOWN = 0,
HT_IOT_PEER_REALTEK = 1,
HT_IOT_PEER_BROADCOM = 2,
HT_IOT_PEER_RALINK = 3,
HT_IOT_PEER_ATHEROS = 4,
HT_IOT_PEER_CISCO = 5,
HT_IOT_PEER_MAX = 6
} HT_IOT_PEER_E, *PHTIOT_PEER_E;
/*
* IOT Action for different AP
*/
typedef enum _HT_IOT_ACTION {
HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
HT_IOT_ACT_CDD_FSYNC = 0x00000080,
HT_IOT_ACT_PURE_N_MODE = 0x00000100,
HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
} HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
#endif //_RTL819XU_HTTYPE_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __INC_QOS_TYPE_H
#define __INC_QOS_TYPE_H
/*
* ACI/AIFSN Field.
* Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
* Note: 1 Byte Length
*/
struct aci_aifsn {
u8 aifsn:4;
u8 acm:1;
u8 aci:2;
u8:1;
};
/*
* Direction Field Values.
* Ref: WMM spec 2.2.11: WME TSPEC Element, p.18.
*/
enum direction_value {
DIR_UP = 0, // 0x00 // UpLink
DIR_DOWN = 1, // 0x01 // DownLink
DIR_DIRECT = 2, // 0x10 // DirectLink
DIR_BI_DIR = 3, // 0x11 // Bi-Direction
};
/*
* TS Info field in WMM TSPEC Element.
* Ref:
* 1. WMM spec 2.2.11: WME TSPEC Element, p.18.
* 2. 8185 QoS code: QOS_TSINFO [def. in QoS_mp.h]
* Note: sizeof 3 Bytes
*/
struct qos_tsinfo {
u16 uc_traffic_type:1; //WMM is reserved
u16 uc_tsid:4;
u16 uc_direction:2;
u16 uc_access_policy:2; //WMM: bit8=0, bit7=1
u16 uc_aggregation:1; //WMM is reserved
u16 uc_psb:1; //WMMSA is APSD
u16 uc_up:3;
u16 uc_ts_info_ack_policy:2; //WMM is reserved
u8 uc_schedule:1; //WMM is reserved
u8:7;
};
/*
* WMM TSPEC Body.
* Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
* Note: sizeof 55 bytes
*/
struct tspec_body {
struct qos_tsinfo ts_info; //u8 TSInfo[3];
u16 nominal_msd_usize;
u16 max_msd_usize;
u32 min_service_itv;
u32 max_service_itv;
u32 inactivity_itv;
u32 suspen_itv;
u32 service_start_time;
u32 min_data_rate;
u32 mean_data_rate;
u32 peak_data_rate;
u32 max_burst_size;
u32 delay_bound;
u32 min_phy_rate;
u16 surplus_bandwidth_allowance;
u16 medium_time;
};
/*
* 802.11 Management frame Status Code field
*/
struct octet_string {
u8 *octet;
u16 length;
};
#define is_ac_valid(ac) (((ac) <= 7) ? true : false)
#endif // #ifndef __INC_QOS_TYPE_H

View File

@ -1,102 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _TSTYPE_H_
#define _TSTYPE_H_
#include "rtl819x_Qos.h"
#define TS_ADDBA_DELAY 60
#define TOTAL_TS_NUM 16
#define TCLAS_NUM 4
/* This define the Tx/Rx directions */
enum tr_select {
TX_DIR = 0,
RX_DIR = 1,
};
union qos_tclas {
struct type_general {
u8 priority;
u8 classifier_type;
u8 mask;
} type_general;
struct type0_eth {
u8 priority;
u8 classifier_type;
u8 mask;
u8 src_addr[6];
u8 dst_addr[6];
u16 type;
} type0_eth;
struct type1_ipv4 {
u8 priority;
u8 classifier_type;
u8 mask;
u8 version;
u8 src_ip[4];
u8 dst_ip[4];
u16 src_port;
u16 dst_port;
u8 dscp;
u8 protocol;
u8 reserved;
} type1_ipv4;
struct type1_ipv6 {
u8 priority;
u8 classifier_type;
u8 mask;
u8 version;
u8 src_ip[16];
u8 dst_ip[16];
u16 src_port;
u16 dst_port;
u8 flow_label[3];
} type1_ipv6;
struct type2_8021q {
u8 priority;
u8 classifier_type;
u8 mask;
u16 tag_type;
} type2_8021q;
};
struct ts_common_info {
struct list_head list;
struct timer_list setup_timer;
struct timer_list inact_timer;
u8 addr[6];
struct tspec_body t_spec;
union qos_tclas t_class[TCLAS_NUM];
u8 t_clas_proc;
u8 t_clas_num;
};
struct tx_ts_record {
struct ts_common_info ts_common_info;
u16 tx_cur_seq;
struct ba_record tx_pending_ba_record;
struct ba_record tx_admitted_ba_record;
u8 add_ba_req_in_progress;
u8 add_ba_req_delayed;
u8 using_ba;
struct timer_list ts_add_ba_timer;
u8 num;
};
struct rx_ts_record {
struct ts_common_info ts_common_info;
u16 rx_indicate_seq;
u16 rx_timeout_indicate_seq;
struct list_head rx_pending_pkt_list;
struct timer_list rx_pkt_pending_timer;
struct ba_record rx_admitted_ba_record;
u16 rx_last_seq_num;
u8 rx_last_frag_num;
u8 num;
};
#endif

View File

@ -1,534 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "ieee80211.h"
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include "rtl819x_TS.h"
static void TsSetupTimeOut(struct timer_list *unused)
{
// Not implement yet
// This is used for WMMSA and ACM , that would send ADDTSReq frame.
}
static void TsInactTimeout(struct timer_list *unused)
{
// Not implement yet
// This is used for WMMSA and ACM.
// This function would be call when TS is no Tx/Rx for some period of time.
}
/********************************************************************************************************************
*function: I still not understand this function, so wait for further implementation
* input: unsigned long data //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
* return: NULL
* notice:
********************************************************************************************************************/
static void RxPktPendingTimeout(struct timer_list *t)
{
struct rx_ts_record *pRxTs = from_timer(pRxTs, t, rx_pkt_pending_timer);
struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
struct rx_reorder_entry *pReorderEntry = NULL;
//u32 flags = 0;
unsigned long flags = 0;
u8 index = 0;
bool bPktInBuf = false;
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
IEEE80211_DEBUG(IEEE80211_DL_REORDER, "==================>%s()\n", __func__);
if (pRxTs->rx_timeout_indicate_seq != 0xffff) {
// Indicate the pending packets sequentially according to SeqNum until meet the gap.
while (!list_empty(&pRxTs->rx_pending_pkt_list)) {
pReorderEntry = list_entry(pRxTs->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
if (index == 0)
pRxTs->rx_indicate_seq = pReorderEntry->SeqNum;
if (SN_LESS(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq) ||
SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq)) {
list_del_init(&pReorderEntry->List);
if (SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq))
pRxTs->rx_indicate_seq = (pRxTs->rx_indicate_seq + 1) % 4096;
IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s: IndicateSeq: %d\n", __func__, pReorderEntry->SeqNum);
ieee->stats_IndicateArray[index] = pReorderEntry->prxb;
index++;
list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
} else {
bPktInBuf = true;
break;
}
}
}
if (index > 0) {
// Set rx_timeout_indicate_seq to 0xffff to indicate no pending packets in buffer now.
pRxTs->rx_timeout_indicate_seq = 0xffff;
// Indicate packets
if (index > REORDER_WIN_SIZE) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
}
ieee80211_indicate_packets(ieee, ieee->stats_IndicateArray, index);
}
if (bPktInBuf && (pRxTs->rx_timeout_indicate_seq == 0xffff)) {
pRxTs->rx_timeout_indicate_seq = pRxTs->rx_indicate_seq;
mod_timer(&pRxTs->rx_pkt_pending_timer,
jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
}
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
}
/********************************************************************************************************************
*function: Add BA timer function
* input: unsigned long data //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
* return: NULL
* notice:
********************************************************************************************************************/
static void TsAddBaProcess(struct timer_list *t)
{
struct tx_ts_record *pTxTs = from_timer(pTxTs, t, ts_add_ba_timer);
u8 num = pTxTs->num;
struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: ADDBA Req is started!! \n", __func__);
}
static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
{
eth_zero_addr(pTsCommonInfo->addr);
memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body));
memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM);
pTsCommonInfo->t_clas_proc = 0;
pTsCommonInfo->t_clas_num = 0;
}
static void ResetTxTsEntry(struct tx_ts_record *pTS)
{
ResetTsCommonInfo(&pTS->ts_common_info);
pTS->tx_cur_seq = 0;
pTS->add_ba_req_in_progress = false;
pTS->add_ba_req_delayed = false;
pTS->using_ba = false;
ResetBaEntry(&pTS->tx_admitted_ba_record); //For BA Originator
ResetBaEntry(&pTS->tx_pending_ba_record);
}
static void ResetRxTsEntry(struct rx_ts_record *pTS)
{
ResetTsCommonInfo(&pTS->ts_common_info);
pTS->rx_indicate_seq = 0xffff; // This indicate the rx_indicate_seq is not used now!!
pTS->rx_timeout_indicate_seq = 0xffff; // This indicate the rx_timeout_indicate_seq is not used now!!
ResetBaEntry(&pTS->rx_admitted_ba_record); // For BA Recipient
}
void TSInitialize(struct ieee80211_device *ieee)
{
struct tx_ts_record *pTxTS = ieee->TxTsRecord;
struct rx_ts_record *pRxTS = ieee->RxTsRecord;
struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry;
u8 count = 0;
IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __func__);
// Initialize Tx TS related info.
INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
for (count = 0; count < TOTAL_TS_NUM; count++) {
//
pTxTS->num = count;
// The timers for the operation of Traffic Stream and Block Ack.
// DLS related timer will be add here in the future!!
timer_setup(&pTxTS->ts_common_info.setup_timer, TsSetupTimeOut,
0);
timer_setup(&pTxTS->ts_common_info.inact_timer, TsInactTimeout,
0);
timer_setup(&pTxTS->ts_add_ba_timer, TsAddBaProcess, 0);
timer_setup(&pTxTS->tx_pending_ba_record.timer, BaSetupTimeOut,
0);
timer_setup(&pTxTS->tx_admitted_ba_record.timer,
TxBaInactTimeout, 0);
ResetTxTsEntry(pTxTS);
list_add_tail(&pTxTS->ts_common_info.list, &ieee->Tx_TS_Unused_List);
pTxTS++;
}
// Initialize Rx TS related info.
INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
for (count = 0; count < TOTAL_TS_NUM; count++) {
pRxTS->num = count;
INIT_LIST_HEAD(&pRxTS->rx_pending_pkt_list);
timer_setup(&pRxTS->ts_common_info.setup_timer, TsSetupTimeOut,
0);
timer_setup(&pRxTS->ts_common_info.inact_timer, TsInactTimeout,
0);
timer_setup(&pRxTS->rx_admitted_ba_record.timer,
RxBaInactTimeout, 0);
timer_setup(&pRxTS->rx_pkt_pending_timer, RxPktPendingTimeout, 0);
ResetRxTsEntry(pRxTS);
list_add_tail(&pRxTS->ts_common_info.list, &ieee->Rx_TS_Unused_List);
pRxTS++;
}
// Initialize unused Rx Reorder List.
INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
for (count = 0; count < REORDER_ENTRY_NUM; count++) {
list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
if (count == (REORDER_ENTRY_NUM - 1))
break;
pRxReorderEntry = &ieee->RxReorderEntry[count + 1];
}
}
static void AdmitTS(struct ieee80211_device *ieee,
struct ts_common_info *pTsCommonInfo, u32 InactTime)
{
del_timer_sync(&pTsCommonInfo->setup_timer);
del_timer_sync(&pTsCommonInfo->inact_timer);
if (InactTime != 0)
mod_timer(&pTsCommonInfo->inact_timer,
jiffies + msecs_to_jiffies(InactTime));
}
static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee,
u8 *Addr, u8 TID,
enum tr_select TxRxSelect)
{
//DIRECTION_VALUE dir;
u8 dir;
bool search_dir[4] = {0};
struct list_head *psearch_list; //FIXME
struct ts_common_info *pRet = NULL;
if (ieee->iw_mode == IW_MODE_MASTER) { //ap mode
if (TxRxSelect == TX_DIR) {
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR] = true;
} else {
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR] = true;
}
} else if (ieee->iw_mode == IW_MODE_ADHOC) {
if (TxRxSelect == TX_DIR)
search_dir[DIR_UP] = true;
else
search_dir[DIR_DOWN] = true;
} else {
if (TxRxSelect == TX_DIR) {
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR] = true;
search_dir[DIR_DIRECT] = true;
} else {
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR] = true;
search_dir[DIR_DIRECT] = true;
}
}
if (TxRxSelect == TX_DIR)
psearch_list = &ieee->Tx_TS_Admit_List;
else
psearch_list = &ieee->Rx_TS_Admit_List;
//for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
for (dir = 0; dir <= DIR_BI_DIR; dir++) {
if (!search_dir[dir])
continue;
list_for_each_entry(pRet, psearch_list, list) {
// IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.ts_info.ucTSID, pRet->TSpec.ts_info.ucDirection);
if (memcmp(pRet->addr, Addr, 6) == 0)
if (pRet->t_spec.ts_info.uc_tsid == TID)
if (pRet->t_spec.ts_info.uc_direction == dir) {
// printk("Bingo! got it\n");
break;
}
}
if (&pRet->list != psearch_list)
break;
}
if (&pRet->list != psearch_list)
return pRet;
else
return NULL;
}
static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
struct tspec_body *pTSPEC, union qos_tclas *pTCLAS, u8 TCLAS_Num,
u8 TCLAS_Proc)
{
u8 count;
if (pTsCommonInfo == NULL)
return;
memcpy(pTsCommonInfo->addr, Addr, 6);
if (pTSPEC != NULL)
memcpy((u8 *)(&(pTsCommonInfo->t_spec)), (u8 *)pTSPEC, sizeof(struct tspec_body));
for (count = 0; count < TCLAS_Num; count++)
memcpy((u8 *)(&(pTsCommonInfo->t_class[count])), (u8 *)pTCLAS, sizeof(union qos_tclas));
pTsCommonInfo->t_clas_proc = TCLAS_Proc;
pTsCommonInfo->t_clas_num = TCLAS_Num;
}
bool GetTs(
struct ieee80211_device *ieee,
struct ts_common_info **ppTS,
u8 *Addr,
u8 TID,
enum tr_select TxRxSelect, //Rx:1, Tx:0
bool bAddNewTs
)
{
u8 UP = 0;
//
// We do not build any TS for Broadcast or Multicast stream.
// So reject these kinds of search here.
//
if (is_multicast_ether_addr(Addr)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
return false;
}
if (ieee->current_network.qos_data.supported == 0) {
UP = 0;
} else {
// In WMM case: we use 4 TID only
if (!is_ac_valid(TID)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __func__, TID);
return false;
}
switch (TID) {
case 0:
case 3:
UP = 0;
break;
case 1:
case 2:
UP = 2;
break;
case 4:
case 5:
UP = 5;
break;
case 6:
case 7:
UP = 7;
break;
}
}
*ppTS = SearchAdmitTRStream(
ieee,
Addr,
UP,
TxRxSelect);
if (*ppTS != NULL) {
return true;
} else {
if (!bAddNewTs) {
IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
return false;
} else {
//
// Create a new Traffic stream for current Tx/Rx
// This is for EDCA and WMM to add a new TS.
// For HCCA or WMMSA, TS cannot be addmit without negotiation.
//
struct tspec_body TSpec;
struct qos_tsinfo *pTSInfo = &TSpec.ts_info;
struct list_head *pUnusedList =
(TxRxSelect == TX_DIR) ?
(&ieee->Tx_TS_Unused_List) :
(&ieee->Rx_TS_Unused_List);
struct list_head *pAddmitList =
(TxRxSelect == TX_DIR) ?
(&ieee->Tx_TS_Admit_List) :
(&ieee->Rx_TS_Admit_List);
enum direction_value Dir = (ieee->iw_mode == IW_MODE_MASTER) ?
((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
if (!list_empty(pUnusedList)) {
(*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list);
list_del_init(&(*ppTS)->list);
if (TxRxSelect == TX_DIR) {
struct tx_ts_record *tmp = container_of(*ppTS, struct tx_ts_record, ts_common_info);
ResetTxTsEntry(tmp);
} else {
struct rx_ts_record *tmp = container_of(*ppTS, struct rx_ts_record, ts_common_info);
ResetRxTsEntry(tmp);
}
IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
// Prepare TS Info related field
pTSInfo->uc_traffic_type = 0; // Traffic type: WMM is reserved in this field
pTSInfo->uc_tsid = UP; // TSID
pTSInfo->uc_direction = Dir; // Direction: if there is DirectLink, this need additional consideration.
pTSInfo->uc_access_policy = 1; // Access policy
pTSInfo->uc_aggregation = 0; // Aggregation
pTSInfo->uc_psb = 0; // Aggregation
pTSInfo->uc_up = UP; // User priority
pTSInfo->uc_ts_info_ack_policy = 0; // Ack policy
pTSInfo->uc_schedule = 0; // Schedule
MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
AdmitTS(ieee, *ppTS, 0);
list_add_tail(&((*ppTS)->list), pAddmitList);
// if there is DirectLink, we need to do additional operation here!!
return true;
} else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __func__);
return false;
}
}
}
}
static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info *pTs,
enum tr_select TxRxSelect)
{
//u32 flags = 0;
unsigned long flags = 0;
del_timer_sync(&pTs->setup_timer);
del_timer_sync(&pTs->inact_timer);
TsInitDelBA(ieee, pTs, TxRxSelect);
if (TxRxSelect == RX_DIR) {
struct rx_reorder_entry *pRxReorderEntry;
struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs;
if (timer_pending(&pRxTS->rx_pkt_pending_timer))
del_timer_sync(&pRxTS->rx_pkt_pending_timer);
while (!list_empty(&pRxTS->rx_pending_pkt_list)) {
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
//pRxReorderEntry = list_entry(&pRxTS->rx_pending_pkt_list.prev,RX_REORDER_ENTRY,List);
pRxReorderEntry = list_entry(pRxTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
list_del_init(&pRxReorderEntry->List);
{
int i = 0;
struct ieee80211_rxb *prxb = pRxReorderEntry->prxb;
if (unlikely(!prxb)) {
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
}
for (i = 0; i < prxb->nr_subframes; i++)
dev_kfree_skb(prxb->subframes[i]);
kfree(prxb);
prxb = NULL;
}
list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
}
} else {
struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs;
del_timer_sync(&pTxTS->ts_add_ba_timer);
}
}
void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr)
{
struct ts_common_info *pTS, *pTmpTS;
printk("===========>%s,%pM\n", __func__, Addr);
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
if (memcmp(pTS->addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
if (memcmp(pTS->addr, Addr, 6) == 0) {
printk("====>remove Tx_TS_admin_list\n");
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
if (memcmp(pTS->addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
if (memcmp(pTS->addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
}
}
}
void RemoveAllTS(struct ieee80211_device *ieee)
{
struct ts_common_info *pTS, *pTmpTS;
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->list);
list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
}
}
void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTxTS)
{
if (!pTxTS->add_ba_req_in_progress) {
pTxTS->add_ba_req_in_progress = true;
if (pTxTS->add_ba_req_delayed) {
IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Delayed Start ADDBA after 60 sec!!\n", __func__);
mod_timer(&pTxTS->ts_add_ba_timer,
jiffies + msecs_to_jiffies(TS_ADDBA_DELAY));
} else {
IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__);
mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); //set 10 ticks
}
} else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__);
}
}

View File

@ -1,170 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* This files contains card eeprom (93c46 or 93c56) programming routines,
* memory is addressed by 16 bits words.
*
* This is part of rtl8180 OpenSource driver.
* Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com>
*
* Parts of this driver are based on the GPL part of the
* official realtek driver.
*
* Parts of this driver are based on the rtl8180 driver skeleton
* from Patric Schenke & Andres Salomon.
*
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
*
* We want to thank the Authors of those projects and the Ndiswrapper
* project Authors.
*/
#include "r8180_93cx6.h"
static void eprom_cs(struct net_device *dev, short bit)
{
u8 cmdreg;
int err;
err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
if (err)
return;
if (bit)
/* enable EPROM */
write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CS_BIT);
else
/* disable EPROM */
write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CS_BIT);
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
static void eprom_ck_cycle(struct net_device *dev)
{
u8 cmdreg;
int err;
err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
if (err)
return;
write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CK_BIT);
force_pci_posting(dev);
udelay(EPROM_DELAY);
read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CK_BIT);
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
static void eprom_w(struct net_device *dev, short bit)
{
u8 cmdreg;
int err;
err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
if (err)
return;
if (bit)
write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_W_BIT);
else
write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_W_BIT);
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
static short eprom_r(struct net_device *dev)
{
u8 bit;
int err;
err = read_nic_byte_E(dev, EPROM_CMD, &bit);
if (err)
return err;
udelay(EPROM_DELAY);
if (bit & EPROM_R_BIT)
return 1;
return 0;
}
static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
{
int i;
for (i = 0; i < len; i++) {
eprom_w(dev, b[i]);
eprom_ck_cycle(dev);
}
}
int eprom_read(struct net_device *dev, u32 addr)
{
struct r8192_priv *priv = ieee80211_priv(dev);
short read_cmd[] = {1, 1, 0};
short addr_str[8];
int i;
int addr_len;
u32 ret;
int err;
ret = 0;
/* enable EPROM programming */
write_nic_byte_E(dev, EPROM_CMD,
(EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
if (priv->epromtype == EPROM_93c56) {
addr_str[7] = addr & 1;
addr_str[6] = addr & BIT(1);
addr_str[5] = addr & BIT(2);
addr_str[4] = addr & BIT(3);
addr_str[3] = addr & BIT(4);
addr_str[2] = addr & BIT(5);
addr_str[1] = addr & BIT(6);
addr_str[0] = addr & BIT(7);
addr_len = 8;
} else {
addr_str[5] = addr & 1;
addr_str[4] = addr & BIT(1);
addr_str[3] = addr & BIT(2);
addr_str[2] = addr & BIT(3);
addr_str[1] = addr & BIT(4);
addr_str[0] = addr & BIT(5);
addr_len = 6;
}
eprom_cs(dev, 1);
eprom_ck_cycle(dev);
eprom_send_bits_string(dev, read_cmd, 3);
eprom_send_bits_string(dev, addr_str, addr_len);
/*
* keep chip pin D to low state while reading.
* I'm unsure if it is necessary, but anyway shouldn't hurt
*/
eprom_w(dev, 0);
for (i = 0; i < 16; i++) {
/* eeprom needs a clk cycle between writing opcode&adr
* and reading data. (eeprom outs a dummy 0)
*/
eprom_ck_cycle(dev);
err = eprom_r(dev);
if (err < 0)
return err;
ret |= err << (15 - i);
}
eprom_cs(dev, 0);
eprom_ck_cycle(dev);
/* disable EPROM programming */
write_nic_byte_E(dev, EPROM_CMD,
(EPROM_CMD_NORMAL << EPROM_CMD_OPERATING_MODE_SHIFT));
return ret;
}

View File

@ -1,25 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This is part of rtl8187 OpenSource driver
* Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
* Released under the terms of GPL (General Public Licence)
*
* Parts of this driver are based on the GPL part of the
* official realtek driver
* Parts of this driver are based on the rtl8180 driver skeleton
* from Patric Schenke & Andres Salomon
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
*
* We want to thank the Authors of such projects and the Ndiswrapper
* project Authors.
*/
/*This files contains card eeprom (93c46 or 93c56) programming routines*/
/*memory is addressed by WORDS*/
#include "r8192U.h"
#include "r8192U_hw.h"
#define EPROM_DELAY 10
int eprom_read(struct net_device *dev, u32 addr); /* reads a 16 bits word */

View File

@ -1,294 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* This is part of the rtl8192 driver
*
* This files contains programming code for the rtl8256
* radio frontend.
*
* *Many* thanks to Realtek Corp. for their great support!
*/
#include "r8192U.h"
#include "r8192U_hw.h"
#include "r819xU_phyreg.h"
#include "r819xU_phy.h"
#include "r8190_rtl8256.h"
/*
* Forward declaration of local functions
*/
static void phy_rf8256_config_para_file(struct net_device *dev);
/*--------------------------------------------------------------------------
* Overview: set RF band width (20M or 40M)
* Input: struct net_device* dev
* WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M
* Output: NONE
* Return: NONE
* Note: 8226 support both 20M and 40 MHz
*--------------------------------------------------------------------------
*/
void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Bandwidth)
{
u8 eRFPath;
struct r8192_priv *priv = ieee80211_priv(dev);
/* for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath;
* eRFPath++)
*/
for (eRFPath = 0; eRFPath < RF90_PATH_MAX; eRFPath++) {
if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
continue;
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
if (priv->card_8192_version == VERSION_819XU_A ||
priv->card_8192_version == VERSION_819XU_B) {
/* 8256 D-cut, E-cut, xiong: consider it later! */
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)eRFPath,
0x0b, bMask12Bits, 0x100); /* phy para:1ba */
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)eRFPath,
0x2c, bMask12Bits, 0x3d7);
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)eRFPath,
0x0e, bMask12Bits, 0x021);
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)eRFPath,
0x14, bMask12Bits, 0x5ab);
} else {
RT_TRACE(COMP_ERR, "%s(): unknown hardware version\n", __func__);
}
break;
case HT_CHANNEL_WIDTH_20_40:
if (priv->card_8192_version == VERSION_819XU_A || priv->card_8192_version == VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0b, bMask12Bits, 0x300); /* phy para:3ba */
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x2c, bMask12Bits, 0x3df);
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0e, bMask12Bits, 0x0a1);
if (priv->chan == 3 || priv->chan == 9)
/* I need to set priv->chan whenever current channel changes */
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x59b);
else
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x14, bMask12Bits, 0x5ab);
} else {
RT_TRACE(COMP_ERR, "%s(): unknown hardware version\n", __func__);
}
break;
default:
RT_TRACE(COMP_ERR, "%s(): unknown Bandwidth: %#X\n", __func__, Bandwidth);
break;
}
}
}
/*--------------------------------------------------------------------------
* Overview: Interface to config 8256
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
*--------------------------------------------------------------------------
*/
void phy_rf8256_config(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
/* Initialize general global value
*
* TODO: Extend RF_PATH_C and RF_PATH_D in the future
*/
priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
/* Config BB and RF */
phy_rf8256_config_para_file(dev);
}
/*--------------------------------------------------------------------------
* Overview: Interface to config 8256
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
*--------------------------------------------------------------------------
*/
static void phy_rf8256_config_para_file(struct net_device *dev)
{
u32 u4RegValue = 0;
u8 eRFPath;
BB_REGISTER_DEFINITION_T *pPhyReg;
struct r8192_priv *priv = ieee80211_priv(dev);
u32 RegOffSetToBeCheck = 0x3;
u32 RegValueToBeCheck = 0x7f1;
u32 RF3_Final_Value = 0;
u8 ConstRetryTimes = 5, RetryTimes = 5;
u8 ret = 0;
/* Initialize RF */
for (eRFPath = (enum rf90_radio_path_e)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) {
if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
continue;
pPhyReg = &priv->PHYRegDef[eRFPath];
/* Joseph test for shorten RF config
* pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, rGlobalCtrl, bMaskDWord);
* ----Store original RFENV control type
*/
switch (eRFPath) {
case RF90_PATH_A:
case RF90_PATH_C:
u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF90_PATH_B:
case RF90_PATH_D:
u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16);
break;
}
/*----Set RF_ENV enable----*/
rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
/*----Set RF_ENV output high----*/
rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
/* Set bit number of Address and Data for RF register */
rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */
rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ??? */
rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0, bMask12Bits, 0xbf);
/* Check RF block (for FPGA platform only)----
* TODO: this function should be removed on ASIC , Emily 2007.2.2
*/
if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (enum rf90_radio_path_e)eRFPath)) {
RT_TRACE(COMP_ERR, "phy_rf8256_config():Check Radio[%d] Fail!!\n", eRFPath);
goto phy_RF8256_Config_ParaFile_Fail;
}
RetryTimes = ConstRetryTimes;
RF3_Final_Value = 0;
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF90_PATH_A:
while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_B:
while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_C:
while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_D:
while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (enum rf90_radio_path_e)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (enum rf90_radio_path_e)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
}
/*----Restore RFENV control type----*/
switch (eRFPath) {
case RF90_PATH_A:
case RF90_PATH_C:
rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF90_PATH_B:
case RF90_PATH_D:
rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
break;
}
if (ret) {
RT_TRACE(COMP_ERR, "%s():Radio[%d] Fail!!", __func__, eRFPath);
goto phy_RF8256_Config_ParaFile_Fail;
}
}
RT_TRACE(COMP_PHY, "PHY Initialization Success\n");
return;
phy_RF8256_Config_ParaFile_Fail:
RT_TRACE(COMP_ERR, "PHY Initialization failed\n");
}
void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel)
{
u32 TxAGC = 0;
struct r8192_priv *priv = ieee80211_priv(dev);
TxAGC = powerlevel;
if (priv->bDynamicTxLowPower) {
if (priv->CustomerID == RT_CID_819x_Netcore)
TxAGC = 0x22;
else
TxAGC += priv->CckPwEnl;
}
if (TxAGC > 0x24)
TxAGC = 0x24;
rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
}
void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel)
{
struct r8192_priv *priv = ieee80211_priv(dev);
/* Joseph TxPower for 8192 testing */
u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
u8 index = 0;
u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
u8 byte0, byte1, byte2, byte3;
powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */
powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0;
powerBase1 = powerlevel; /* MCS rates */
powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
for (index = 0; index < 6; index++) {
writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2) ? powerBase0 : powerBase1);
byte0 = (u8)(writeVal & 0x7f);
byte1 = (u8)((writeVal & 0x7f00) >> 8);
byte2 = (u8)((writeVal & 0x7f0000) >> 16);
byte3 = (u8)((writeVal & 0x7f000000) >> 24);
if (byte0 > 0x24)
/* Max power index = 0x24 */
byte0 = 0x24;
if (byte1 > 0x24)
byte1 = 0x24;
if (byte2 > 0x24)
byte2 = 0x24;
if (byte3 > 0x24)
byte3 = 0x24;
/* for tx power track */
if (index == 3) {
writeVal_tmp = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
priv->Pwr_Track = writeVal_tmp;
}
if (priv->bDynamicTxHighPower) {
/*Add by Jacken 2008/03/06
*Emily, 20080613. Set low tx power for both MCS and legacy OFDM
*/
writeVal = 0x03030303;
} else {
writeVal = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
}
rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
}
}

View File

@ -1,24 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This is part of the rtl8180-sa2400 driver
* released under the GPL (See file COPYING for details).
* Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
*
*
* This files contains programming code for the rtl8256
* radio frontend.
*
* *Many* thanks to Realtek Corp. for their great support!
*/
#ifndef RTL8225H
#define RTL8225H
#define RTL819X_TOTAL_RF_PATH 2 /* for 8192U */
void phy_set_rf8256_bandwidth(struct net_device *dev,
enum ht_channel_width bandwidth);
void phy_rf8256_config(struct net_device *dev);
void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel);
void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,188 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/****************************************************************************
* -----------------------------DEGUGFS STUFF-------------------------
****************************************************************************/
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include "r8192U.h"
#define KBUILD_MODNAME "r8192u_usb"
static int rtl8192_usb_stats_ap_show(struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
struct ieee80211_network *target;
list_for_each_entry(target, &ieee->network_list, list) {
const char *wpa = "non_WPA";
if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
wpa = "WPA";
seq_printf(m, "%s %s\n", target->ssid, wpa);
}
return 0;
}
static int rtl8192_usb_registers_show(struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
int i, n, max = 0xff;
u8 byte_rd;
seq_puts(m, "\n####################page 0##################\n ");
for (n = 0; n <= max;) {
seq_printf(m, "\nD: %2x > ", n);
for (i = 0; i < 16 && n <= max; i++, n++) {
read_nic_byte(dev, 0x000 | n, &byte_rd);
seq_printf(m, "%2x ", byte_rd);
}
}
seq_puts(m, "\n####################page 1##################\n ");
for (n = 0; n <= max;) {
seq_printf(m, "\nD: %2x > ", n);
for (i = 0; i < 16 && n <= max; i++, n++) {
read_nic_byte(dev, 0x100 | n, &byte_rd);
seq_printf(m, "%2x ", byte_rd);
}
}
seq_puts(m, "\n####################page 3##################\n ");
for (n = 0; n <= max;) {
seq_printf(m, "\nD: %2x > ", n);
for (i = 0; i < 16 && n <= max; i++, n++) {
read_nic_byte(dev, 0x300 | n, &byte_rd);
seq_printf(m, "%2x ", byte_rd);
}
}
seq_putc(m, '\n');
return 0;
}
static int rtl8192_usb_stats_tx_show(struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
struct r8192_priv *priv = ieee80211_priv(dev);
seq_printf(m,
"TX VI priority ok int: %lu\n"
"TX VI priority error int: %lu\n"
"TX VO priority ok int: %lu\n"
"TX VO priority error int: %lu\n"
"TX BE priority ok int: %lu\n"
"TX BE priority error int: %lu\n"
"TX BK priority ok int: %lu\n"
"TX BK priority error int: %lu\n"
"TX MANAGE priority ok int: %lu\n"
"TX MANAGE priority error int: %lu\n"
"TX BEACON priority ok int: %lu\n"
"TX BEACON priority error int: %lu\n"
"TX queue resume: %lu\n"
"TX queue stopped?: %d\n"
"TX fifo overflow: %lu\n"
"TX VI queue: %d\n"
"TX VO queue: %d\n"
"TX BE queue: %d\n"
"TX BK queue: %d\n"
"TX VI dropped: %lu\n"
"TX VO dropped: %lu\n"
"TX BE dropped: %lu\n"
"TX BK dropped: %lu\n"
"TX total data packets %lu\n",
priv->stats.txviokint,
priv->stats.txvierr,
priv->stats.txvookint,
priv->stats.txvoerr,
priv->stats.txbeokint,
priv->stats.txbeerr,
priv->stats.txbkokint,
priv->stats.txbkerr,
priv->stats.txmanageokint,
priv->stats.txmanageerr,
priv->stats.txbeaconokint,
priv->stats.txbeaconerr,
priv->stats.txresumed,
netif_queue_stopped(dev),
priv->stats.txoverflow,
atomic_read(&(priv->tx_pending[VI_PRIORITY])),
atomic_read(&(priv->tx_pending[VO_PRIORITY])),
atomic_read(&(priv->tx_pending[BE_PRIORITY])),
atomic_read(&(priv->tx_pending[BK_PRIORITY])),
priv->stats.txvidrop,
priv->stats.txvodrop,
priv->stats.txbedrop,
priv->stats.txbkdrop,
priv->stats.txdatapkt
);
return 0;
}
static int rtl8192_usb_stats_rx_show(struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
struct r8192_priv *priv = ieee80211_priv(dev);
seq_printf(m,
"RX packets: %lu\n"
"RX urb status error: %lu\n"
"RX invalid urb error: %lu\n",
priv->stats.rxoktotal,
priv->stats.rxstaterr,
priv->stats.rxurberr);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(rtl8192_usb_stats_rx);
DEFINE_SHOW_ATTRIBUTE(rtl8192_usb_stats_tx);
DEFINE_SHOW_ATTRIBUTE(rtl8192_usb_stats_ap);
DEFINE_SHOW_ATTRIBUTE(rtl8192_usb_registers);
void rtl8192_debugfs_init_one(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct dentry *parent_dir = debugfs_lookup(KBUILD_MODNAME, NULL);
struct dentry *dir = debugfs_create_dir(dev->name, parent_dir);
debugfs_create_file("stats-rx", 0444, dir, dev, &rtl8192_usb_stats_rx_fops);
debugfs_create_file("stats-tx", 0444, dir, dev, &rtl8192_usb_stats_tx_fops);
debugfs_create_file("stats-ap", 0444, dir, dev, &rtl8192_usb_stats_ap_fops);
debugfs_create_file("registers", 0444, dir, dev, &rtl8192_usb_registers_fops);
priv->debugfs_dir = dir;
}
void rtl8192_debugfs_exit_one(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
debugfs_remove_recursive(priv->debugfs_dir);
}
void rtl8192_debugfs_rename_one(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct dentry *parent_dir = debugfs_lookup(KBUILD_MODNAME, NULL);
debugfs_rename(parent_dir, priv->debugfs_dir, parent_dir, dev->name);
}
void rtl8192_debugfs_init(void)
{
debugfs_create_dir(KBUILD_MODNAME, NULL);
}
void rtl8192_debugfs_exit(void)
{
debugfs_remove_recursive(debugfs_lookup(KBUILD_MODNAME, NULL));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,176 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*****************************************************************************
* Copyright(c) 2007, RealTEK Technology Inc. All Right Reserved.
*
* Module: Hal819xUsbDM.h (RTL8192 Header H File)
*
*
* Note: For dynamic control definition constant structure.
*
*
* Export:
*
* Abbrev:
*
* History:
* Data Who Remark
* 10/04/2007 MHC Create initial version.
*
*****************************************************************************/
/* Check to see if the file has been included already. */
#ifndef __R8192UDM_H__
#define __R8192UDM_H__
/*--------------------------Define Parameters-------------------------------*/
#define DM_DIG_THRESH_HIGH 40
#define DM_DIG_THRESH_LOW 35
#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
#define DM_DIG_HIGH_PWR_THRESH_LOW 70
#define BW_AUTO_SWITCH_HIGH_LOW 25
#define BW_AUTO_SWITCH_LOW_HIGH 30
#define DM_DIG_BACKOFF 12
#define DM_DIG_MAX 0x36
#define DM_DIG_MIN 0x1c
#define DM_DIG_MIN_NETCORE 0x12
#define RX_PATH_SELECTION_SS_TH_LOW 30
#define RX_PATH_SELECTION_DIFF_TH 18
#define RATE_ADAPTIVE_TH_HIGH 50
#define RATE_ADAPTIVE_TH_LOW_20M 30
#define RATE_ADAPTIVE_TH_LOW_40M 10
#define VERY_LOW_RSSI 15
#define CTS_TO_SELF_TH_VAL 30
/* defined by vivi, for tx power track */
#define E_FOR_TX_POWER_TRACK 300
/* Dynamic Tx Power Control Threshold */
#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68
#define TX_POWER_NEAR_FIELD_THRESH_LOW 62
/* added by amy for atheros AP */
#define TX_POWER_ATHEROAP_THRESH_HIGH 78
#define TX_POWER_ATHEROAP_THRESH_LOW 72
/* defined by vivi, for showing on UI */
#define CURRENT_TX_RATE_REG 0x1b8
#define INITIAL_TX_RATE_REG 0x1b9
#define TX_RETRY_COUNT_REG 0x1ac
#define REG_C38_TH 20
/*--------------------------Define Parameters-------------------------------*/
/*------------------------------Define structure----------------------------*/
enum dig_algorithm {
DIG_ALGO_BY_FALSE_ALARM = 0,
DIG_ALGO_BY_RSSI = 1,
};
enum dynamic_init_gain_state {
DM_STA_DIG_OFF = 0,
DM_STA_DIG_ON,
DM_STA_DIG_MAX
};
enum dig_connect {
DIG_DISCONNECT = 0,
DIG_CONNECT = 1,
};
enum dig_pkt_detection_threshold {
DIG_PD_AT_LOW_POWER = 0,
DIG_PD_AT_NORMAL_POWER = 1,
DIG_PD_AT_HIGH_POWER = 2,
};
enum dig_cck_cs_ratio_state {
DIG_CS_RATIO_LOWER = 0,
DIG_CS_RATIO_HIGHER = 1,
};
/* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */
struct dig {
u8 dig_enable_flag;
enum dig_algorithm dig_algorithm;
u8 dig_algorithm_switch;
long rssi_low_thresh;
long rssi_high_thresh;
long rssi_high_power_lowthresh;
long rssi_high_power_highthresh;
enum dynamic_init_gain_state dig_state;
enum dynamic_init_gain_state dig_highpwr_state;
enum dig_connect cur_connect_state;
enum dig_connect pre_connect_state;
enum dig_pkt_detection_threshold curpd_thstate;
enum dig_pkt_detection_threshold prepd_thstate;
enum dig_cck_cs_ratio_state curcs_ratio_state;
enum dig_cck_cs_ratio_state precs_ratio_state;
u32 pre_ig_value;
u32 cur_ig_value;
u8 backoff_val;
u8 rx_gain_range_min;
long rssi_val;
};
enum cck_rx_path_method {
CCK_RX_VERSION_1 = 0,
CCK_RX_VERSION_2 = 1,
};
struct dynamic_rx_path_sel {
enum cck_rx_path_method cck_method;
u8 cck_rx_path;
u8 disabled_rf;
u8 rf_rssi[4];
u8 rf_enable_rssi_th[4];
long cck_pwdb_sta[4];
};
struct tx_config_cmd {
u32 cmd_op; /* Command packet type. */
u32 cmd_length; /* Command packet length. */
u32 cmd_value;
};
/*------------------------------Define structure----------------------------*/
/*------------------------Export global variable----------------------------*/
extern struct dig dm_digtable;
extern u8 dm_shadow[16][256];
/*------------------------Export global variable----------------------------*/
/*------------------------Export Marco Definition---------------------------*/
/*------------------------Export Marco Definition---------------------------*/
/*--------------------------Exported Function prototype---------------------*/
void init_hal_dm(struct net_device *dev);
void deinit_hal_dm(struct net_device *dev);
void hal_dm_watchdog(struct net_device *dev);
void init_rate_adaptive(struct net_device *dev);
void dm_txpower_trackingcallback(struct work_struct *work);
void dm_restore_dynamic_mechanism_state(struct net_device *dev);
void dm_force_tx_fw_info(struct net_device *dev,
u32 force_type, u32 force_value);
void dm_init_edca_turbo(struct net_device *dev);
void dm_rf_operation_test_callback(unsigned long data);
void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
void dm_fsync_work_callback(struct work_struct *work);
void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
void dm_initialize_txpower_tracking(struct net_device *dev);
/*--------------------------Exported Function prototype---------------------*/
#endif /*__R8192UDM_H__ */
/* End of r8192U_dm.h */

View File

@ -1,246 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This is part of rtl8187 OpenSource driver.
* Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
*
* Parts of this driver are based on the GPL part of the
* official Realtek driver.
* Parts of this driver are based on the rtl8180 driver skeleton
* from Patric Schenke & Andres Salomon.
* Parts of this driver are based on the Intel Pro Wireless
* 2100 GPL driver.
*
* We want to thank the Authors of those projects
* and the Ndiswrapper project Authors.
*/
/* Mariusz Matuszek added full registers definition with Realtek's name */
/* this file contains register definitions for the rtl8187 MAC controller */
#ifndef R8192_HW
#define R8192_HW
#define RTL8187_REQT_READ 0xc0
#define RTL8187_REQT_WRITE 0x40
#define RTL8187_REQ_GET_REGS 0x05
#define RTL8187_REQ_SET_REGS 0x05
#define MAX_TX_URB 5
#define MAX_RX_URB 16
#define R8180_MAX_RETRY 255
#define RX_URB_SIZE 9100
#define RTL8190_EEPROM_ID 0x8129
#define EEPROM_VID 0x02
#define EEPROM_PID 0x04
#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C
#define EEPROM_TX_POWER_DIFF 0x1F
#define EEPROM_THERMAL_METER 0x20
#define EEPROM_PW_DIFF 0x21 //0x21
#define EEPROM_CRYSTAL_CAP 0x22 //0x22
#define EEPROM_TX_PW_INDEX_CCK 0x23 //0x23
#define EEPROM_TX_PW_INDEX_OFDM_24G 0x24 //0x24~0x26
#define EEPROM_TX_PW_INDEX_CCK_V1 0x29 //0x29~0x2B
#define EEPROM_TX_PW_INDEX_OFDM_24G_V1 0x2C //0x2C~0x2E
#define EEPROM_TX_PW_INDEX_VER 0x27 //0x27
#define EEPROM_DEFAULT_THERNAL_METER 0x7
#define EEPROM_DEFAULT_PW_DIFF 0x4
#define EEPROM_DEFAULT_CRYSTAL_CAP 0x5
#define EEPROM_DEFAULT_TX_POWER 0x1010
#define EEPROM_CUSTOMER_ID 0x7B //0x7B:CustomerID
#define EEPROM_CHANNEL_PLAN 0x16 //0x7C
#define EEPROM_CID_RUNTOP 0x2
#define EEPROM_CID_DLINK 0x8
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
#define AC_PARAM_ECW_MAX_OFFSET 12
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
//#endif
enum _RTL8192Usb_HW {
MAC0 = 0x000,
MAC4 = 0x004,
#define BB_GLOBAL_RESET_BIT 0x1
BB_GLOBAL_RESET = 0x020, // BasebandGlobal Reset Register
BSSIDR = 0x02E, // BSSID Register
CMDR = 0x037, // Command register
#define CR_RE 0x08
#define CR_TE 0x04
SIFS = 0x03E, // SIFS register
#define TCR_MXDMA_2048 7
#define TCR_LRL_OFFSET 0
#define TCR_SRL_OFFSET 8
#define TCR_MXDMA_OFFSET 21
#define TCR_SAT BIT(24) // Enable Rate depedent ack timeout timer
RCR = 0x044, // Receive Configuration Register
#define MAC_FILTER_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(5) | \
BIT(12) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | \
BIT(22) | BIT(23))
#define RX_FIFO_THRESHOLD_MASK (BIT(13) | BIT(14) | BIT(15))
#define RX_FIFO_THRESHOLD_SHIFT 13
#define RX_FIFO_THRESHOLD_NONE 7
#define MAX_RX_DMA_MASK (BIT(8) | BIT(9) | BIT(10))
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
#define RCR_ONLYERLPKT BIT(31) // Early Receiving based on Packet Size.
#define RCR_CBSSID BIT(23) // Accept BSSID match packet
#define RCR_APWRMGT BIT(22) // Accept power management packet
#define RCR_AMF BIT(20) // Accept management type frame
#define RCR_ACF BIT(19) // Accept control type frame
#define RCR_ADF BIT(18) // Accept data type frame
#define RCR_AICV BIT(12) // Accept ICV error packet
#define RCR_ACRC32 BIT(5) // Accept CRC32 error packet
#define RCR_AB BIT(3) // Accept broadcast packet
#define RCR_AM BIT(2) // Accept multicast packet
#define RCR_APM BIT(1) // Accept physical match packet
#define RCR_AAP BIT(0) // Accept all unicast packet
SLOT_TIME = 0x049, // Slot Time Register
ACK_TIMEOUT = 0x04c, // Ack Timeout Register
EDCAPARA_BE = 0x050, // EDCA Parameter of AC BE
EDCAPARA_BK = 0x054, // EDCA Parameter of AC BK
EDCAPARA_VO = 0x058, // EDCA Parameter of AC VO
EDCAPARA_VI = 0x05C, // EDCA Parameter of AC VI
BCN_TCFG = 0x062, // Beacon Time Configuration
#define BCN_TCFG_CW_SHIFT 8
#define BCN_TCFG_IFS 0
BCN_INTERVAL = 0x070, // Beacon Interval (TU)
ATIMWND = 0x072, // ATIM Window Size (TU)
BCN_DRV_EARLY_INT = 0x074, // Driver Early Interrupt Time (TU). Time to send interrupt to notify to change beacon content before TBTT
BCN_DMATIME = 0x076, // Beacon DMA and ATIM interrupt time (US). Indicates the time before TBTT to perform beacon queue DMA
BCN_ERR_THRESH = 0x078, // Beacon Error Threshold
RWCAM = 0x0A0, //IN 8190 Data Sheet is called CAMcmd
WCAMI = 0x0A4, // Software write CAM input content
SECR = 0x0B0, //Security Configuration Register
#define SCR_TxUseDK BIT(0) //Force Tx Use Default Key
#define SCR_RxUseDK BIT(1) //Force Rx Use Default Key
#define SCR_TxEncEnable BIT(2) //Enable Tx Encryption
#define SCR_RxDecEnable BIT(3) //Enable Rx Decryption
#define SCR_SKByA2 BIT(4) //Search kEY BY A2
#define SCR_NoSKMC BIT(5) //No Key Search for Multicast
//----------------------------------------------------------------------------
// 8190 CPU General Register (offset 0x100, 4 byte)
//----------------------------------------------------------------------------
#define CPU_CCK_LOOPBACK 0x00030000
#define CPU_GEN_SYSTEM_RESET 0x00000001
#define CPU_GEN_FIRMWARE_RESET 0x00000008
#define CPU_GEN_BOOT_RDY 0x00000010
#define CPU_GEN_FIRM_RDY 0x00000020
#define CPU_GEN_PUT_CODE_OK 0x00000080
#define CPU_GEN_BB_RST 0x00000100
#define CPU_GEN_PWR_STB_CPU 0x00000004
#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19
#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1
CPU_GEN = 0x100, // CPU Reset Register
AcmHwCtrl = 0x171, // ACM Hardware Control Register
//----------------------------------------------------------------------------
////
//// 8190 AcmHwCtrl bits (offset 0x171, 1 byte)
////----------------------------------------------------------------------------
//
#define AcmHw_BeqEn BIT(1)
RQPN1 = 0x180, // Reserved Queue Page Number , Vo Vi, Be, Bk
RQPN2 = 0x184, // Reserved Queue Page Number, HCCA, Cmd, Mgnt, High
RQPN3 = 0x188, // Reserved Queue Page Number, Bcn, Public,
QPNR = 0x1D0, //0x1F0, // Queue Packet Number report per TID
#define BW_OPMODE_5G BIT(1)
#define BW_OPMODE_20MHZ BIT(2)
BW_OPMODE = 0x300, // Bandwidth operation mode
MSR = 0x303, // Media Status register
#define MSR_LINK_MASK (BIT(0) | BIT(1))
#define MSR_LINK_MANAGED 2
#define MSR_LINK_NONE 0
#define MSR_LINK_SHIFT 0
#define MSR_LINK_ADHOC 1
#define MSR_LINK_MASTER 3
RETRY_LIMIT = 0x304, // Retry Limit [15:8]-short, [7:0]-long
#define RETRY_LIMIT_SHORT_SHIFT 8
#define RETRY_LIMIT_LONG_SHIFT 0
RRSR = 0x310, // Response Rate Set
#define RRSR_1M BIT(0)
#define RRSR_2M BIT(1)
#define RRSR_5_5M BIT(2)
#define RRSR_11M BIT(3)
#define RRSR_6M BIT(4)
#define RRSR_9M BIT(5)
#define RRSR_12M BIT(6)
#define RRSR_18M BIT(7)
#define RRSR_24M BIT(8)
#define RRSR_36M BIT(9)
#define RRSR_48M BIT(10)
#define RRSR_54M BIT(11)
#define BRSR_AckShortPmb BIT(23) // CCK ACK: use Short Preamble or not.
UFWP = 0x318,
RATR0 = 0x320, // Rate Adaptive Table register1
DRIVER_RSSI = 0x32c, // Driver tell Firmware current RSSI
//----------------------------------------------------------------------------
// 8190 Rate Adaptive Table Register (offset 0x320, 4 byte)
//----------------------------------------------------------------------------
//CCK
#define RATR_1M 0x00000001
#define RATR_2M 0x00000002
#define RATR_55M 0x00000004
#define RATR_11M 0x00000008
//OFDM
#define RATR_6M 0x00000010
#define RATR_9M 0x00000020
#define RATR_12M 0x00000040
#define RATR_18M 0x00000080
#define RATR_24M 0x00000100
#define RATR_36M 0x00000200
#define RATR_48M 0x00000400
#define RATR_54M 0x00000800
//MCS 1 Spatial Stream
#define RATR_MCS0 0x00001000
#define RATR_MCS1 0x00002000
#define RATR_MCS2 0x00004000
#define RATR_MCS3 0x00008000
#define RATR_MCS4 0x00010000
#define RATR_MCS5 0x00020000
#define RATR_MCS6 0x00040000
#define RATR_MCS7 0x00080000
//MCS 2 Spatial Stream
#define RATR_MCS8 0x00100000
#define RATR_MCS9 0x00200000
#define RATR_MCS10 0x00400000
#define RATR_MCS11 0x00800000
#define RATR_MCS12 0x01000000
#define RATR_MCS13 0x02000000
#define RATR_MCS14 0x04000000
#define RATR_MCS15 0x08000000
// ALL CCK Rate
#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\
RATR_24M | RATR_36M | RATR_48M | RATR_54M)
#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | RATR_MCS3 |\
RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | RATR_MCS7)
#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | RATR_MCS11 |\
RATR_MCS12 | RATR_MCS13 | RATR_MCS14 | RATR_MCS15)
EPROM_CMD = 0xfe58,
#define Cmd9346CR_9356SEL BIT(4)
#define EPROM_CMD_OPERATING_MODE_SHIFT 6
#define EPROM_CMD_NORMAL 0
#define EPROM_CMD_PROGRAM 2
#define EPROM_CS_BIT BIT(3)
#define EPROM_CK_BIT BIT(2)
#define EPROM_W_BIT BIT(1)
#define EPROM_R_BIT BIT(0)
};
//----------------------------------------------------------------------------
// 818xB AnaParm & AnaParm2 Register
//----------------------------------------------------------------------------
#define GPI 0x108
#endif

View File

@ -1,943 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
*
* This file contains wireless extension handlers.
*
* This is part of rtl8180 OpenSource driver.
* Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
*
* Parts of this driver are based on the GPL part
* of the official realtek driver.
*
* Parts of this driver are based on the rtl8180 driver skeleton
* from Patric Schenke & Andres Salomon.
*
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
*
* We want to thank the Authors of those projects and the Ndiswrapper
* project Authors.
*
*****************************************************************************/
#include <linux/string.h>
#include "r8192U.h"
#include "r8192U_hw.h"
#include "ieee80211/dot11d.h"
#include "r8192U_wx.h"
#define RATE_COUNT 12
static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
#ifndef ENETDOWN
#define ENETDOWN 1
#endif
static int r8192_wx_get_freq(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
}
static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
}
static int r8192_wx_get_rate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
}
static int r8192_wx_set_rate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_rts(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_rts(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
}
static int r8192_wx_set_power(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_power(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
}
static int r8192_wx_force_reset(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
priv->force_reset = *extra;
mutex_unlock(&priv->wx_mutex);
return 0;
}
static int r8192_wx_set_rawtx(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int ret;
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_crcmon(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int *parms = (int *)extra;
int enable = (parms[0] > 0);
mutex_lock(&priv->wx_mutex);
if (enable)
priv->crcmon = 1;
else
priv->crcmon = 0;
DMESG("bad CRC in monitor mode are %s",
priv->crcmon ? "accepted" : "rejected");
mutex_unlock(&priv->wx_mutex);
return 0;
}
static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int ret;
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
rtl8192_set_rxconf(dev);
mutex_unlock(&priv->wx_mutex);
return ret;
}
struct iw_range_with_scan_capa {
/* Informative stuff (to choose between different interface) */
__u32 throughput; /* To give an idea... */
/* In theory this value should be the maximum benchmarked
* TCP/IP throughput, because with most of these devices the
* bit rate is meaningless (overhead an co) to estimate how
* fast the connection will go and pick the fastest one.
* I suggest people to play with Netperf or any benchmark...
*/
/* NWID (or domain id) */
__u32 min_nwid; /* Minimal NWID we are able to set */
__u32 max_nwid; /* Maximal NWID we are able to set */
/* Old Frequency (backward compat - moved lower ) */
__u16 old_num_channels;
__u8 old_num_frequency;
/* Scan capabilities */
__u8 scan_capa;
};
static int rtl8180_wx_get_range(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct iw_range *range = (struct iw_range *)extra;
struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
struct r8192_priv *priv = ieee80211_priv(dev);
u16 val;
int i;
wrqu->data.length = sizeof(*range);
memset(range, 0, sizeof(*range));
/* Let's try to keep this struct in the same order as in
* linux/include/wireless.h
*/
/* TODO: See what values we can set, and remove the ones we can't
* set, or fill them with some default data.
*/
/* ~5 Mb/s real (802.11b) */
range->throughput = 5 * 1000 * 1000;
/* TODO: Not used in 802.11b? */
/* range->min_nwid; */ /* Minimal NWID we are able to set */
/* TODO: Not used in 802.11b? */
/* range->max_nwid; */ /* Maximal NWID we are able to set */
/* Old Frequency (backward compat - moved lower ) */
/* range->old_num_channels; */
/* range->old_num_frequency; */
/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
if (priv->rf_set_sens)
range->sensitivity = priv->max_sens; /* signal level threshold range */
range->max_qual.qual = 100;
/* TODO: Find real max RSSI and stick here */
range->max_qual.level = 0;
range->max_qual.noise = 0x100 - 98;
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range->avg_qual.level = 0x100 - 78;
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
range->num_bitrates = RATE_COUNT;
for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
range->bitrate[i] = rtl8180_rates[i];
range->min_frag = MIN_FRAG_THRESHOLD;
range->max_frag = MAX_FRAG_THRESHOLD;
range->min_pmp = 0;
range->max_pmp = 5000000;
range->min_pmt = 0;
range->max_pmt = 65535 * 1000;
range->pmp_flags = IW_POWER_PERIOD;
range->pmt_flags = IW_POWER_TIMEOUT;
range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 16;
/* range->retry_capa; */ /* What retry options are supported */
/* range->retry_flags; */ /* How to decode max/min retry limit */
/* range->r_time_flags; */ /* How to decode max/min retry life */
/* range->min_retry; */ /* Minimal number of retries */
/* range->max_retry; */ /* Maximal number of retries */
/* range->min_r_time; */ /* Minimal retry lifetime */
/* range->max_r_time; */ /* Maximal retry lifetime */
for (i = 0, val = 0; i < 14; i++) {
/* Include only legal frequencies for some countries */
if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i + 1]) {
range->freq[val].i = i + 1;
range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
range->freq[val].e = 1;
val++;
} else {
/* FIXME: do we need to set anything for channels */
/* we don't use ? */
}
if (val == IW_MAX_FREQUENCIES)
break;
}
range->num_frequency = val;
range->num_channels = val;
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
tmp->scan_capa = 0x01;
return 0;
}
static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
int ret = 0;
if (!priv->up)
return -ENETDOWN;
if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
return -EAGAIN;
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
struct iw_scan_req *req = (struct iw_scan_req *)b;
if (req->essid_len) {
int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
ieee->current_network.ssid_len = len;
memcpy(ieee->current_network.ssid, req->essid, len);
}
}
mutex_lock(&priv->wx_mutex);
if (priv->ieee80211->state != IEEE80211_LINKED) {
priv->ieee80211->scanning = 0;
ieee80211_softmac_scan_syncro(priv->ieee80211);
ret = 0;
} else {
ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
}
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
if (!priv->up)
return -ENETDOWN;
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_essid(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int ret;
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_essid(struct net_device *dev,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
}
static int r8192_wx_set_frag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
if (wrqu->frag.disabled) {
priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
} else {
if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
wrqu->frag.value > MAX_FRAG_THRESHOLD)
return -EINVAL;
priv->ieee80211->fts = wrqu->frag.value & ~0x1;
}
return 0;
}
static int r8192_wx_get_frag(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
wrqu->frag.value = priv->ieee80211->fts;
wrqu->frag.fixed = 0; /* no auto select */
wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
return 0;
}
static int r8192_wx_set_wap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
/* struct sockaddr *temp = (struct sockaddr *)awrq; */
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_get_wap(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
}
static int r8192_wx_get_enc(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *key)
{
struct r8192_priv *priv = ieee80211_priv(dev);
return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
}
static int r8192_wx_set_enc(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *key)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
int ret;
u32 hwkey[4] = {0, 0, 0, 0};
u8 mask = 0xff;
u32 key_idx = 0;
u8 zero_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
int i;
if (!priv->up)
return -ENETDOWN;
mutex_lock(&priv->wx_mutex);
RT_TRACE(COMP_SEC, "Setting SW wep key");
ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
mutex_unlock(&priv->wx_mutex);
/* sometimes, the length is zero while we do not type key value */
if (wrqu->encoding.length != 0) {
for (i = 0; i < 4; i++) {
hwkey[i] |= key[4 * i + 0] & mask;
if (i == 1 && (4 * i + 1) == wrqu->encoding.length)
mask = 0x00;
if (i == 3 && (4 * i + 1) == wrqu->encoding.length)
mask = 0x00;
hwkey[i] |= (key[4 * i + 1] & mask) << 8;
hwkey[i] |= (key[4 * i + 2] & mask) << 16;
hwkey[i] |= (key[4 * i + 3] & mask) << 24;
}
#define CONF_WEP40 0x4
#define CONF_WEP104 0x14
switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
case 0:
key_idx = ieee->tx_keyidx;
break;
case 1:
key_idx = 0;
break;
case 2:
key_idx = 1;
break;
case 3:
key_idx = 2;
break;
case 4:
key_idx = 3;
break;
default:
break;
}
if (wrqu->encoding.length == 0x5) {
ieee->pairwise_key_type = KEY_TYPE_WEP40;
EnableHWSecurityConfig8192(dev);
setKey(dev,
key_idx, /* EntryNo */
key_idx, /* KeyIndex */
KEY_TYPE_WEP40, /* KeyType */
zero_addr[key_idx],
0, /* DefaultKey */
hwkey); /* KeyContent */
} else if (wrqu->encoding.length == 0xd) {
ieee->pairwise_key_type = KEY_TYPE_WEP104;
EnableHWSecurityConfig8192(dev);
setKey(dev,
key_idx, /* EntryNo */
key_idx, /* KeyIndex */
KEY_TYPE_WEP104, /* KeyType */
zero_addr[key_idx],
0, /* DefaultKey */
hwkey); /* KeyContent */
} else {
netdev_warn(dev, "wrong type in WEP, not WEP40 and WEP104\n");
}
}
return ret;
}
static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
union iwreq_data *wrqu, char *p)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int *parms = (int *)p;
int mode = parms[0];
priv->ieee80211->active_scan = mode;
return 1;
}
static int r8192_wx_set_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
int err = 0;
mutex_lock(&priv->wx_mutex);
if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
wrqu->retry.disabled){
err = -EINVAL;
goto exit;
}
if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
err = -EINVAL;
goto exit;
}
if (wrqu->retry.value > R8180_MAX_RETRY) {
err = -EINVAL;
goto exit;
}
if (wrqu->retry.flags & IW_RETRY_MAX) {
priv->retry_rts = wrqu->retry.value;
DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
} else {
priv->retry_data = wrqu->retry.value;
DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
}
/* FIXME !
* We might try to write directly the TX config register
* or to restart just the (R)TX process.
* I'm unsure if whole reset is really needed
*/
rtl8192_commit(dev);
exit:
mutex_unlock(&priv->wx_mutex);
return err;
}
static int r8192_wx_get_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
wrqu->retry.disabled = 0; /* can't be disabled */
if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
IW_RETRY_LIFETIME)
return -EINVAL;
if (wrqu->retry.flags & IW_RETRY_MAX) {
wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
wrqu->retry.value = priv->retry_rts;
} else {
wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
wrqu->retry.value = priv->retry_data;
}
return 0;
}
static int r8192_wx_get_sens(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
if (!priv->rf_set_sens)
return -1; /* we have not this support for this radio */
wrqu->sens.value = priv->sens;
return 0;
}
static int r8192_wx_set_sens(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct r8192_priv *priv = ieee80211_priv(dev);
short err = 0;
mutex_lock(&priv->wx_mutex);
if (!priv->rf_set_sens) {
err = -1; /* we have not this support for this radio */
goto exit;
}
if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
priv->sens = wrqu->sens.value;
else
err = -EINVAL;
exit:
mutex_unlock(&priv->wx_mutex);
return err;
}
/* hw security need to reorganized. */
static int r8192_wx_set_enc_ext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
{
u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 zero[6] = {0};
u32 key[4] = {0};
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
struct iw_point *encoding = &wrqu->encoding;
u8 idx = 0, alg = 0, group = 0;
if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
/* none is not allowed to use hwsec WB 2008.07.01 */
goto end_hw_sec;
/* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
alg = (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP : ext->alg;
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx)
idx--;
group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
if ((!group) || (ieee->iw_mode == IW_MODE_ADHOC) || (alg == KEY_TYPE_WEP40)) {
if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
alg = KEY_TYPE_WEP104;
ieee->pairwise_key_type = alg;
EnableHWSecurityConfig8192(dev);
}
memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
setKey(dev,
idx, /* EntryNao */
idx, /* KeyIndex */
alg, /* KeyType */
zero, /* MacAddr */
0, /* DefaultKey */
key); /* KeyContent */
} else if (group) {
ieee->group_key_type = alg;
setKey(dev,
idx, /* EntryNo */
idx, /* KeyIndex */
alg, /* KeyType */
broadcast_addr, /* MacAddr */
0, /* DefaultKey */
key); /* KeyContent */
} else { /* pairwise key */
setKey(dev,
4, /* EntryNo */
idx, /* KeyIndex */
alg, /* KeyType */
(u8 *)ieee->ap_mac_addr,/* MacAddr */
0, /* DefaultKey */
key); /* KeyContent */
}
}
end_hw_sec:
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
int ret = 0;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_auth(priv->ieee80211, info, &data->param, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_mlme(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int r8192_wx_set_gen_ie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
int ret = 0;
struct r8192_priv *priv = ieee80211_priv(dev);
mutex_lock(&priv->wx_mutex);
ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
mutex_unlock(&priv->wx_mutex);
return ret;
}
static int dummy(struct net_device *dev, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
return -1;
}
static iw_handler r8192_wx_handlers[] = {
NULL, /* SIOCSIWCOMMIT */
r8192_wx_get_name, /* SIOCGIWNAME */
dummy, /* SIOCSIWNWID */
dummy, /* SIOCGIWNWID */
r8192_wx_set_freq, /* SIOCSIWFREQ */
r8192_wx_get_freq, /* SIOCGIWFREQ */
r8192_wx_set_mode, /* SIOCSIWMODE */
r8192_wx_get_mode, /* SIOCGIWMODE */
r8192_wx_set_sens, /* SIOCSIWSENS */
r8192_wx_get_sens, /* SIOCGIWSENS */
NULL, /* SIOCSIWRANGE */
rtl8180_wx_get_range, /* SIOCGIWRANGE */
NULL, /* SIOCSIWPRIV */
NULL, /* SIOCGIWPRIV */
NULL, /* SIOCSIWSTATS */
NULL, /* SIOCGIWSTATS */
dummy, /* SIOCSIWSPY */
dummy, /* SIOCGIWSPY */
NULL, /* SIOCGIWTHRSPY */
NULL, /* SIOCWIWTHRSPY */
r8192_wx_set_wap, /* SIOCSIWAP */
r8192_wx_get_wap, /* SIOCGIWAP */
r8192_wx_set_mlme, /* MLME-- */
dummy, /* SIOCGIWAPLIST -- deprecated */
r8192_wx_set_scan, /* SIOCSIWSCAN */
r8192_wx_get_scan, /* SIOCGIWSCAN */
r8192_wx_set_essid, /* SIOCSIWESSID */
r8192_wx_get_essid, /* SIOCGIWESSID */
dummy, /* SIOCSIWNICKN */
dummy, /* SIOCGIWNICKN */
NULL, /* -- hole -- */
NULL, /* -- hole -- */
r8192_wx_set_rate, /* SIOCSIWRATE */
r8192_wx_get_rate, /* SIOCGIWRATE */
r8192_wx_set_rts, /* SIOCSIWRTS */
r8192_wx_get_rts, /* SIOCGIWRTS */
r8192_wx_set_frag, /* SIOCSIWFRAG */
r8192_wx_get_frag, /* SIOCGIWFRAG */
dummy, /* SIOCSIWTXPOW */
dummy, /* SIOCGIWTXPOW */
r8192_wx_set_retry, /* SIOCSIWRETRY */
r8192_wx_get_retry, /* SIOCGIWRETRY */
r8192_wx_set_enc, /* SIOCSIWENCODE */
r8192_wx_get_enc, /* SIOCGIWENCODE */
r8192_wx_set_power, /* SIOCSIWPOWER */
r8192_wx_get_power, /* SIOCGIWPOWER */
NULL, /*---hole---*/
NULL, /*---hole---*/
r8192_wx_set_gen_ie, /* NULL, */ /* SIOCSIWGENIE */
NULL, /* SIOCSIWGENIE */
r8192_wx_set_auth,/* NULL, */ /* SIOCSIWAUTH */
NULL,/* r8192_wx_get_auth, */ /* NULL, */ /* SIOCSIWAUTH */
r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
NULL,/* r8192_wx_get_enc_ext, *//* NULL, */ /* SIOCSIWENCODEEXT */
NULL, /* SIOCSIWPMKSA */
NULL, /*---hole---*/
};
static const struct iw_priv_args r8192_private_args[] = {
{
SIOCIWFIRSTPRIV + 0x0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
},
{
SIOCIWFIRSTPRIV + 0x1,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
},
{
SIOCIWFIRSTPRIV + 0x2,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
},
{
SIOCIWFIRSTPRIV + 0x3,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
}
};
static iw_handler r8192_private_handler[] = {
r8192_wx_set_crcmon,
r8192_wx_set_scan_type,
r8192_wx_set_rawtx,
r8192_wx_force_reset,
};
struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
struct iw_statistics *wstats = &priv->wstats;
int tmp_level = 0;
int tmp_qual = 0;
int tmp_noise = 0;
if (ieee->state < IEEE80211_LINKED) {
wstats->qual.qual = 0;
wstats->qual.level = 0;
wstats->qual.noise = 0;
wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
return wstats;
}
tmp_level = (&ieee->current_network)->stats.rssi;
tmp_qual = (&ieee->current_network)->stats.signal;
tmp_noise = (&ieee->current_network)->stats.noise;
wstats->qual.level = tmp_level;
wstats->qual.qual = tmp_qual;
wstats->qual.noise = tmp_noise;
wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
return wstats;
}
const struct iw_handler_def r8192_wx_handlers_def = {
.standard = r8192_wx_handlers,
.num_standard = ARRAY_SIZE(r8192_wx_handlers),
.private = r8192_private_handler,
.num_private = ARRAY_SIZE(r8192_private_handler),
.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
.get_wireless_stats = r8192_get_wireless_stats,
.private_args = (struct iw_priv_args *)r8192_private_args,
};

View File

@ -1,24 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This is part of rtl8180 OpenSource driver - v 0.3
* Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com>
*
* Parts of this driver are based on the GPL part of the official realtek driver
* Parts of this driver are based on the rtl8180 driver skeleton from Patric
* Schenke & Andres Salomon
* Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
*
* We want to thank the Authors of such projects and the Ndiswrapper project
* Authors.
*/
/* this file (will) contains wireless extension handlers */
#ifndef R8180_WX_H
#define R8180_WX_H
extern const struct iw_handler_def r8192_wx_handlers_def;
/* Enable the rtl819x_core.c to share this function, david 2008.9.22 */
struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
#endif

View File

@ -1,508 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
*
* (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
*
* Module: r819xusb_cmdpkt.c
* (RTL8190 TX/RX command packet handler Source C File)
*
* Note: The module is responsible for handling TX and RX command packet.
* 1. TX : Send set and query configuration command packet.
* 2. RX : Receive tx feedback, beacon state, query configuration
* command packet.
*
* Function:
*
* Export:
*
* Abbrev:
*
* History:
*
* Date Who Remark
* 05/06/2008 amy Create initial version porting from
* windows driver.
*
******************************************************************************/
#include "r8192U.h"
#include "r819xU_cmdpkt.h"
rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct sk_buff *skb;
struct cb_desc *tcb_desc;
/* Get TCB and local buffer from common pool.
* (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
*/
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
if (!skb)
return RT_STATUS_FAILURE;
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
tcb_desc->bLastIniPkt = 0;
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
skb_put_data(skb, pData, DataLen);
tcb_desc->txbuf_size = (u16)DataLen;
if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
(priv->ieee80211->queue_stop)) {
RT_TRACE(COMP_FIRMWARE, "=== NULL packet ======> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb, dev);
}
return RT_STATUS_SUCCESS;
}
static void cmpk_count_txstatistic(struct net_device *dev, struct cmd_pkt_tx_feedback *pstx_fb)
{
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
RT_RF_POWER_STATE rtState;
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
(pu1Byte)(&rtState));
/* When RF is off, we should not count the packet for hw/sw synchronize
* reason, ie. there may be a duration while sw switch is changed and
* hw switch is being changed.
*/
if (rtState == eRfOff)
return;
#endif
#ifdef TODO
if (pAdapter->bInHctTest)
return;
#endif
/* We can not know the packet length and transmit type:
* broadcast or uni or multicast. So the relative statistics
* must be collected in tx feedback info.
*/
if (pstx_fb->tok) {
priv->stats.txfeedbackok++;
priv->stats.txoktotal++;
priv->stats.txokbytestotal += pstx_fb->pkt_length;
priv->stats.txokinperiod++;
/* We can not make sure broadcast/multicast or unicast mode. */
if (pstx_fb->pkt_type == PACKET_MULTICAST) {
priv->stats.txmulticast++;
priv->stats.txbytesmulticast += pstx_fb->pkt_length;
} else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
priv->stats.txbroadcast++;
priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
} else {
priv->stats.txunicast++;
priv->stats.txbytesunicast += pstx_fb->pkt_length;
}
} else {
priv->stats.txfeedbackfail++;
priv->stats.txerrtotal++;
priv->stats.txerrbytestotal += pstx_fb->pkt_length;
/* We can not make sure broadcast/multicast or unicast mode. */
if (pstx_fb->pkt_type == PACKET_MULTICAST)
priv->stats.txerrmulticast++;
else if (pstx_fb->pkt_type == PACKET_BROADCAST)
priv->stats.txerrbroadcast++;
else
priv->stats.txerrunicast++;
}
priv->stats.txretrycount += pstx_fb->retry_cnt;
priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
}
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_feedback()
*
* Overview: The function is responsible for extract the message inside TX
* feedbck message from firmware. It will contain dedicated info in
* ws-06-0063-rtl8190-command-packet-specification.
* Please refer to chapter "TX Feedback Element".
* We have to read 20 bytes in the command packet.
*
* Input: struct net_device *dev
* u8 *pmsg - Msg Ptr of the command packet.
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/08/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------
*/
static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
{
struct r8192_priv *priv = ieee80211_priv(dev);
struct cmd_pkt_tx_feedback rx_tx_fb;
priv->stats.txfeedback++;
/* 1. Extract TX feedback info from RFD to temp structure buffer. */
/* It seems that FW use big endian(MIPS) and DRV use little endian in
* windows OS. So we have to read the content byte by byte or transfer
* endian type before copy the message copy.
*/
/* Use pointer to transfer structure memory. */
memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(struct cmd_pkt_tx_feedback));
/* 2. Use tx feedback info to count TX statistics. */
cmpk_count_txstatistic(dev, &rx_tx_fb);
/* Comment previous method for TX statistic function. */
/* Collect info TX feedback packet to fill TCB. */
/* We can not know the packet length and transmit type: broadcast or uni
* or multicast.
*/
}
static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
u16 tx_rate;
/* 87B have to S/W beacon for DTM encryption_cmn. */
if (priv->ieee80211->current_network.mode == IEEE_A ||
priv->ieee80211->current_network.mode == IEEE_N_5G ||
(priv->ieee80211->current_network.mode == IEEE_N_24G &&
(!priv->ieee80211->pHTInfo->bCurSuppCCK))) {
tx_rate = 60;
DMESG("send beacon frame tx rate is 6Mbpm\n");
} else {
tx_rate = 10;
DMESG("send beacon frame tx rate is 1Mbpm\n");
}
rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */
}
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_interrupt_status()
*
* Overview: The function is responsible for extract the message from
* firmware. It will contain dedicated info in
* ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
* Please refer to chapter "Interrupt Status Element".
*
* Input: struct net_device *dev
* u8 *pmsg - Message Pointer of the command packet.
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Add this for rtl8192 porting from windows code.
*
*---------------------------------------------------------------------------
*/
static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
{
struct cmd_pkt_interrupt_status rx_intr_status; /* */
struct r8192_priv *priv = ieee80211_priv(dev);
DMESG("---> cmpk_Handle_Interrupt_Status()\n");
/* 1. Extract TX feedback info from RFD to temp structure buffer. */
/* It seems that FW use big endian(MIPS) and DRV use little endian in
* windows OS. So we have to read the content byte by byte or transfer
* endian type before copy the message copy.
*/
rx_intr_status.length = pmsg[1];
if (rx_intr_status.length != (sizeof(struct cmd_pkt_interrupt_status) - 2)) {
DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
return;
}
/* Statistics of beacon for ad-hoc mode. */
if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
/* 2 maybe need endian transform? */
rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
DMESG("interrupt status = 0x%x\n",
rx_intr_status.interrupt_status);
if (rx_intr_status.interrupt_status & ISR_TX_BCN_OK) {
priv->ieee80211->bibsscoordinator = true;
priv->stats.txbeaconokint++;
} else if (rx_intr_status.interrupt_status & ISR_TX_BCN_ERR) {
priv->ieee80211->bibsscoordinator = false;
priv->stats.txbeaconerr++;
}
if (rx_intr_status.interrupt_status & ISR_BCN_TIMER_INTR)
cmdpkt_beacontimerinterrupt_819xusb(dev);
}
/* Other information in interrupt status we need? */
DMESG("<---- cmpk_handle_interrupt_status()\n");
}
/*-----------------------------------------------------------------------------
* Function: cmpk_count_tx_status()
*
* Overview: Count aggregated tx status from firmwar of one type rx command
* packet element id = RX_TX_STATUS.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------
*/
static void cmpk_count_tx_status(struct net_device *dev,
cmpk_tx_status_t *pstx_status)
{
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
RT_RF_POWER_STATE rtstate;
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
(pu1Byte)(&rtState));
/* When RF is off, we should not count the packet for hw/sw synchronize
* reason, ie. there may be a duration while sw switch is changed and
* hw switch is being changed.
*/
if (rtState == eRfOff)
return;
#endif
priv->stats.txfeedbackok += pstx_status->txok;
priv->stats.txoktotal += pstx_status->txok;
priv->stats.txfeedbackfail += pstx_status->txfail;
priv->stats.txerrtotal += pstx_status->txfail;
priv->stats.txretrycount += pstx_status->txretry;
priv->stats.txfeedbackretry += pstx_status->txretry;
priv->stats.txmulticast += pstx_status->txmcok;
priv->stats.txbroadcast += pstx_status->txbcok;
priv->stats.txunicast += pstx_status->txucok;
priv->stats.txerrmulticast += pstx_status->txmcfail;
priv->stats.txerrbroadcast += pstx_status->txbcfail;
priv->stats.txerrunicast += pstx_status->txucfail;
priv->stats.txbytesmulticast += pstx_status->txmclength;
priv->stats.txbytesbroadcast += pstx_status->txbclength;
priv->stats.txbytesunicast += pstx_status->txuclength;
priv->stats.last_packet_rate = pstx_status->rate;
}
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_status()
*
* Overview: Firmware add a new tx feedback status to reduce rx command
* packet buffer operation load.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------
*/
static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
{
cmpk_tx_status_t rx_tx_sts;
memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t));
/* 2. Use tx feedback info to count TX statistics. */
cmpk_count_tx_status(dev, &rx_tx_sts);
}
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_rate_history()
*
* Overview: Firmware add a new tx rate history
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------
*/
static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
{
cmpk_tx_rahis_t *ptxrate;
u8 i, j;
u16 length = sizeof(cmpk_tx_rahis_t);
u32 *ptemp;
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
(pu1Byte)(&rtState));
/* When RF is off, we should not count the packet for hw/sw synchronize
* reason, ie. there may be a duration while sw switch is changed and
* hw switch is being changed.
*/
if (rtState == eRfOff)
return;
#endif
ptemp = (u32 *)pmsg;
/* Do endian transfer to word alignment(16 bits) for windows system.
* You must do different endian transfer for linux and MAC OS
*/
for (i = 0; i < (length/4); i++) {
u16 temp1, temp2;
temp1 = ptemp[i] & 0x0000FFFF;
temp2 = ptemp[i] >> 16;
ptemp[i] = (temp1 << 16) | temp2;
}
ptxrate = (cmpk_tx_rahis_t *)pmsg;
if (!ptxrate)
return;
for (i = 0; i < 16; i++) {
/* Collect CCK rate packet num */
if (i < 4)
priv->stats.txrate.cck[i] += ptxrate->cck[i];
/* Collect OFDM rate packet num */
if (i < 8)
priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
for (j = 0; j < 4; j++)
priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
}
}
/*-----------------------------------------------------------------------------
* Function: cmpk_message_handle_rx()
*
* Overview: In the function, we will capture different RX command packet
* info. Every RX command packet element has different message
* length and meaning in content. We only support three type of RX
* command packet now. Please refer to document
* ws-06-0063-rtl8190-command-packet-specification.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/06/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------
*/
u32 cmpk_message_handle_rx(struct net_device *dev,
struct ieee80211_rx_stats *pstats)
{
int total_length;
u8 cmd_length, exe_cnt = 0;
u8 element_id;
u8 *pcmd_buff;
/* 0. Check inpt arguments. It is a command queue message or
* pointer is null.
*/
if (!pstats)
return 0; /* This is not a command packet. */
/* 1. Read received command packet message length from RFD. */
total_length = pstats->Length;
/* 2. Read virtual address from RFD. */
pcmd_buff = pstats->virtual_address;
/* 3. Read command packet element id and length. */
element_id = pcmd_buff[0];
/* 4. Check every received command packet content according to different
* element type. Because FW may aggregate RX command packet to
* minimize transmit time between DRV and FW.
*/
/* Add a counter to prevent the lock in the loop from being held too
* long
*/
while (total_length > 0 && exe_cnt++ < 100) {
/* We support aggregation of different cmd in the same packet */
element_id = pcmd_buff[0];
switch (element_id) {
case RX_TX_FEEDBACK:
cmpk_handle_tx_feedback(dev, pcmd_buff);
cmd_length = CMPK_RX_TX_FB_SIZE;
break;
case RX_INTERRUPT_STATUS:
cmpk_handle_interrupt_status(dev, pcmd_buff);
cmd_length = sizeof(struct cmd_pkt_interrupt_status);
break;
case BOTH_QUERY_CONFIG:
cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
break;
case RX_TX_STATUS:
cmpk_handle_tx_status(dev, pcmd_buff);
cmd_length = CMPK_RX_TX_STS_SIZE;
break;
case RX_TX_PER_PKT_FEEDBACK:
/* You must at lease add a switch case element here,
* Otherwise, we will jump to default case.
*/
cmd_length = CMPK_RX_TX_FB_SIZE;
break;
case RX_TX_RATE_HISTORY:
cmpk_handle_tx_rate_history(dev, pcmd_buff);
cmd_length = CMPK_TX_RAHIS_SIZE;
break;
default:
RT_TRACE(COMP_ERR, "---->%s():unknown CMD Element\n",
__func__);
return 1; /* This is a command packet. */
}
total_length -= cmd_length;
pcmd_buff += cmd_length;
}
return 1; /* This is a command packet. */
}

View File

@ -1,190 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef R819XUSB_CMDPKT_H
#define R819XUSB_CMDPKT_H
/* Different command packet have dedicated message length and definition. */
#define CMPK_RX_TX_FB_SIZE sizeof(struct cmd_pkt_tx_feedback) /* 20 */
#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(struct cmd_pkt_set_configuration) /* 16 */
#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t)
#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t)
/* 2008/05/08 amy For USB constant. */
#define ISR_TX_BCN_OK BIT(27) /* Transmit Beacon OK */
#define ISR_TX_BCN_ERR BIT(26) /* Transmit Beacon Error */
#define ISR_BCN_TIMER_INTR BIT(13) /* Beacon Timer Interrupt */
/* Define element ID of command packet. */
/*------------------------------Define structure----------------------------*/
/* Define different command packet structure. */
/* 1. RX side: TX feedback packet. */
struct cmd_pkt_tx_feedback {
/* DWORD 0 */
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
/* Change tx feedback info field. */
/*------TX Feedback Info Field */
u8 TID:4;
u8 fail_reason:3;
u8 tok:1; /* Transmit ok. */
u8 reserve1:4;
u8 pkt_type:2;
u8 bandwidth:1;
u8 qos_pkt:1;
/* DWORD 1 */
u8 reserve2;
/*------TX Feedback Info Field */
u8 retry_cnt;
u16 pkt_id;
/* DWORD 3 */
u16 seq_num;
u8 s_rate; /* Start rate. */
u8 f_rate; /* Final rate. */
/* DWORD 4 */
u8 s_rts_rate;
u8 f_rts_rate;
u16 pkt_length;
/* DWORD 5 */
u16 reserve3;
u16 duration;
};
/* 2. RX side: Interrupt status packet. It includes Beacon State,
* Beacon Timer Interrupt and other useful information in MAC ISR Reg.
*/
struct cmd_pkt_interrupt_status {
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
u16 reserve;
u32 interrupt_status; /* Interrupt Status. */
};
/* 3. TX side: Set configuration packet. */
struct cmd_pkt_set_configuration {
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
u16 reserve1;
/* Configuration info. */
u8 cfg_reserve1:3;
u8 cfg_size:2;
u8 cfg_type:2;
u8 cfg_action:1;
u8 cfg_reserve2;
u8 cfg_page:4;
u8 cfg_reserve3:4;
u8 cfg_offset;
u32 value;
u32 mask;
};
/* 4. Both side : TX/RX query configuration packet. The query structure is the
* same as set configuration.
*/
#define cmpk_query_cfg cmd_pkt_set_configuration
/* 5. Multi packet feedback status. */
typedef struct tag_tx_stats_feedback {
/* For endian transfer --> Driver will not the same as
* firmware structure.
*/
/* DW 0 */
u16 reserve1;
u8 length; /* Command packet length */
u8 element_id; /* Command packet type */
/* DW 1 */
u16 txfail; /* Tx fail count */
u16 txok; /* Tx ok count */
/* DW 2 */
u16 txmcok; /* Tx multicast */
u16 txretry; /* Tx retry count */
/* DW 3 */
u16 txucok; /* Tx unicast */
u16 txbcok; /* Tx broadcast */
/* DW 4 */
u16 txbcfail;
u16 txmcfail;
/* DW 5 */
u16 reserve2;
u16 txucfail;
/* DW 6-8 */
u32 txmclength;
u32 txbclength;
u32 txuclength;
/* DW 9 */
u16 reserve3_23;
u8 reserve3_1;
u8 rate;
} __packed cmpk_tx_status_t;
/* 6. Debug feedback message. */
/* Define RX debug message */
typedef struct tag_rx_debug_message_feedback {
/* For endian transfer --> for driver */
/* DW 0 */
u16 reserve1;
u8 length; /* Command packet length */
u8 element_id; /* Command packet type */
/* DW 1-?? */
/* Variable debug message. */
} cmpk_rx_dbginfo_t;
/* Define transmit rate history. For big endian format. */
typedef struct tag_tx_rate_history {
/* For endian transfer --> for driver */
/* DW 0 */
u8 element_id; /* Command packet type */
u8 length; /* Command packet length */
u16 reserved1;
/* DW 1-2 CCK rate counter */
u16 cck[4];
/* DW 3-6 */
u16 ofdm[8];
/* DW 7-14 BW=0 SG=0
* DW 15-22 BW=1 SG=0
* DW 23-30 BW=0 SG=1
* DW 31-38 BW=1 SG=1
*/
u16 ht_mcs[4][16];
} __packed cmpk_tx_rahis_t;
typedef enum tag_command_packet_directories {
RX_TX_FEEDBACK = 0,
RX_INTERRUPT_STATUS = 1,
TX_SET_CONFIG = 2,
BOTH_QUERY_CONFIG = 3,
RX_TX_STATUS = 4,
RX_DBGINFO_FEEDBACK = 5,
RX_TX_PER_PKT_FEEDBACK = 6,
RX_TX_RATE_HISTORY = 7,
RX_CMD_ELE_MAX
} cmpk_element_e;
typedef enum _rt_status {
RT_STATUS_SUCCESS,
RT_STATUS_FAILURE,
RT_STATUS_PENDING,
RT_STATUS_RESOURCE
} rt_status, *prt_status;
u32 cmpk_message_handle_rx(struct net_device *dev,
struct ieee80211_rx_stats *pstats);
rt_status SendTxCommandPacket(struct net_device *dev,
void *pData, u32 DataLen);
#endif

View File

@ -1,340 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/**************************************************************************************************
* Procedure: Init boot code/firmware code/data session
*
* Description: This routine will initialize firmware. If any error occurs during the initialization
* process, the routine shall terminate immediately and return fail.
* NIC driver should call NdisOpenFile only from MiniportInitialize.
*
* Arguments: The pointer of the adapter
* Returns:
* NDIS_STATUS_FAILURE - the following initialization process should be terminated
* NDIS_STATUS_SUCCESS - if firmware initialization process success
**************************************************************************************************/
#include "r8192U.h"
#include "r8192U_hw.h"
#include "r819xU_firmware_img.h"
#include "r819xU_firmware.h"
#include <linux/firmware.h>
static void firmware_init_param(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
rt_firmware *pfirmware = priv->pFirmware;
pfirmware->cmdpacket_frag_threshold = GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
}
/*
* segment the img and use the ptr and length to remember info on each segment
*
*/
static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
u32 buffer_len)
{
struct r8192_priv *priv = ieee80211_priv(dev);
bool rt_status = true;
u16 frag_threshold;
u16 frag_length, frag_offset = 0;
int i;
rt_firmware *pfirmware = priv->pFirmware;
struct sk_buff *skb;
unsigned char *seg_ptr;
struct cb_desc *tcb_desc;
u8 bLastIniPkt;
u8 index;
firmware_init_param(dev);
/* Fragmentation might be required */
frag_threshold = pfirmware->cmdpacket_frag_threshold;
do {
if ((buffer_len - frag_offset) > frag_threshold) {
frag_length = frag_threshold;
bLastIniPkt = 0;
} else {
frag_length = buffer_len - frag_offset;
bLastIniPkt = 1;
}
/* Allocate skb buffer to contain firmware info and tx descriptor info
* add 4 to avoid packet appending overflow.
*/
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
if (!skb)
return false;
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
tcb_desc->bLastIniPkt = bLastIniPkt;
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
seg_ptr = skb->data;
/*
* Transform from little endian to big endian
* and pending zero
*/
for (i = 0; i < frag_length; i += 4) {
*seg_ptr++ = ((i+0) < frag_length)?code_virtual_address[i+3] : 0;
*seg_ptr++ = ((i+1) < frag_length)?code_virtual_address[i+2] : 0;
*seg_ptr++ = ((i+2) < frag_length)?code_virtual_address[i+1] : 0;
*seg_ptr++ = ((i+3) < frag_length)?code_virtual_address[i+0] : 0;
}
tcb_desc->txbuf_size = (u16)i;
skb_put(skb, i);
index = tcb_desc->queue_index;
if (!priv->ieee80211->check_nic_enough_desc(dev, index) ||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[index])) ||
(priv->ieee80211->queue_stop)) {
RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb, dev);
}
code_virtual_address += frag_length;
frag_offset += frag_length;
} while (frag_offset < buffer_len);
return rt_status;
}
/*
* Procedure: Check whether main code is download OK. If OK, turn on CPU
*
* Description: CPU register locates in different page against general register.
* Switch to CPU register in the begin and switch back before return
*
*
* Arguments: The pointer of the adapter
*
* Returns:
* NDIS_STATUS_FAILURE - the following initialization process should
* be terminated
* NDIS_STATUS_SUCCESS - if firmware initialization process success
*/
static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
{
bool rt_status = true;
int check_putcodeOK_time = 200000, check_bootOk_time = 200000;
u32 CPU_status = 0;
/* Check whether put code OK */
do {
read_nic_dword(dev, CPU_GEN, &CPU_status);
if (CPU_status&CPU_GEN_PUT_CODE_OK)
break;
} while (check_putcodeOK_time--);
if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
} else {
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
}
/* Turn On CPU */
read_nic_dword(dev, CPU_GEN, &CPU_status);
write_nic_byte(dev, CPU_GEN,
(u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
mdelay(1000);
/* Check whether CPU boot OK */
do {
read_nic_dword(dev, CPU_GEN, &CPU_status);
if (CPU_status&CPU_GEN_BOOT_RDY)
break;
} while (check_bootOk_time--);
if (!(CPU_status&CPU_GEN_BOOT_RDY))
goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
else
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
return rt_status;
CPUCheckMainCodeOKAndTurnOnCPU_Fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
rt_status = false;
return rt_status;
}
static bool CPUcheck_firmware_ready(struct net_device *dev)
{
bool rt_status = true;
int check_time = 200000;
u32 CPU_status = 0;
/* Check Firmware Ready */
do {
read_nic_dword(dev, CPU_GEN, &CPU_status);
if (CPU_status&CPU_GEN_FIRM_RDY)
break;
} while (check_time--);
if (!(CPU_status&CPU_GEN_FIRM_RDY))
goto CPUCheckFirmwareReady_Fail;
else
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
return rt_status;
CPUCheckFirmwareReady_Fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
rt_status = false;
return rt_status;
}
bool init_firmware(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
bool rt_status = true;
u32 file_length = 0;
u8 *mapped_file = NULL;
u32 init_step = 0;
enum opt_rst_type_e rst_opt = OPT_SYSTEM_RESET;
enum firmware_init_step_e starting_state = FW_INIT_STEP0_BOOT;
rt_firmware *pfirmware = priv->pFirmware;
const struct firmware *fw_entry;
const char *fw_name[3] = { "RTL8192U/boot.img",
"RTL8192U/main.img",
"RTL8192U/data.img"};
int rc;
RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
/* it is called by reset */
rst_opt = OPT_SYSTEM_RESET;
starting_state = FW_INIT_STEP0_BOOT;
/* TODO: system reset */
} else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
/* it is called by Initialize */
rst_opt = OPT_FIRMWARE_RESET;
starting_state = FW_INIT_STEP2_DATA;
} else {
RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n");
}
/*
* Download boot, main, and data image for System reset.
* Download data image for firmware reset
*/
for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
/*
* Open image file, and map file to continuous memory if open file success.
* or read image file from array. Default load from IMG file
*/
if (rst_opt == OPT_SYSTEM_RESET) {
rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev);
if (rc < 0) {
RT_TRACE(COMP_ERR, "request firmware fail!\n");
goto download_firmware_fail;
}
if (fw_entry->size > sizeof(pfirmware->firmware_buf)) {
RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
goto download_firmware_fail;
}
if (init_step != FW_INIT_STEP1_MAIN) {
memcpy(pfirmware->firmware_buf, fw_entry->data, fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size;
} else {
memset(pfirmware->firmware_buf, 0, 128);
memcpy(&pfirmware->firmware_buf[128], fw_entry->data, fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size + 128;
}
pfirmware->firmware_buf_size = file_length;
} else if (rst_opt == OPT_FIRMWARE_RESET) {
/* we only need to download data.img here */
mapped_file = pfirmware->firmware_buf;
file_length = pfirmware->firmware_buf_size;
}
/* Download image file */
/* The firmware download process is just as following,
* 1. that is each packet will be segmented and inserted to the wait queue.
* 2. each packet segment will be put in the skb_buff packet.
* 3. each skb_buff packet data content will already include the firmware info
* and Tx descriptor info
*/
rt_status = fw_download_code(dev, mapped_file, file_length);
if (rst_opt == OPT_SYSTEM_RESET)
release_firmware(fw_entry);
if (!rt_status)
goto download_firmware_fail;
switch (init_step) {
case FW_INIT_STEP0_BOOT:
/* Download boot
* initialize command descriptor.
* will set polling bit when firmware code is also configured
*/
pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
/* mdelay(1000); */
/*
* To initialize IMEM, CPU move code from 0x80000080,
* hence, we send 0x80 byte packet
*/
break;
case FW_INIT_STEP1_MAIN:
/* Download firmware code. Wait until Boot Ready and Turn on CPU */
pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
/* Check Put Code OK and Turn On CPU */
rt_status = CPUcheck_maincodeok_turnonCPU(dev);
if (!rt_status) {
RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n");
goto download_firmware_fail;
}
pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
break;
case FW_INIT_STEP2_DATA:
/* download initial data code */
pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
mdelay(1);
rt_status = CPUcheck_firmware_ready(dev);
if (!rt_status) {
RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n", rt_status);
goto download_firmware_fail;
}
/* wait until data code is initialized ready.*/
pfirmware->firmware_status = FW_STATUS_5_READY;
break;
}
}
RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
return rt_status;
download_firmware_fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
rt_status = false;
return rt_status;
}
MODULE_FIRMWARE("RTL8192U/boot.img");
MODULE_FIRMWARE("RTL8192U/main.img");
MODULE_FIRMWARE("RTL8192U/data.img");

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __INC_FIRMWARE_H
#define __INC_FIRMWARE_H
#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) \
(4 * ((v) / 4) - 8 - USB_HWDESC_HEADER_LEN)
enum firmware_init_step_e {
FW_INIT_STEP0_BOOT = 0,
FW_INIT_STEP1_MAIN = 1,
FW_INIT_STEP2_DATA = 2,
};
enum opt_rst_type_e {
OPT_SYSTEM_RESET = 0,
OPT_FIRMWARE_RESET = 1,
};
#endif

View File

@ -1,549 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*Created on 2008/ 7/16, 5:31*/
#include <linux/types.h>
#include "r819xU_firmware_img.h"
u32 Rtl8192UsbPHY_REGArray[] = {
0x0, };
u32 Rtl8192UsbPHY_REG_1T2RArray[] = {
0x800, 0x00000000,
0x804, 0x00000001,
0x808, 0x0000fc00,
0x80c, 0x0000001c,
0x810, 0x801010aa,
0x814, 0x008514d0,
0x818, 0x00000040,
0x81c, 0x00000000,
0x820, 0x00000004,
0x824, 0x00690000,
0x828, 0x00000004,
0x82c, 0x00e90000,
0x830, 0x00000004,
0x834, 0x00690000,
0x838, 0x00000004,
0x83c, 0x00e90000,
0x840, 0x00000000,
0x844, 0x00000000,
0x848, 0x00000000,
0x84c, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x65a965a9,
0x85c, 0x65a965a9,
0x860, 0x001f0010,
0x864, 0x007f0010,
0x868, 0x001f0010,
0x86c, 0x007f0010,
0x870, 0x0f100f70,
0x874, 0x0f100f70,
0x878, 0x00000000,
0x87c, 0x00000000,
0x880, 0x6870e36c,
0x884, 0xe3573600,
0x888, 0x4260c340,
0x88c, 0x0000ff00,
0x890, 0x00000000,
0x894, 0xfffffffe,
0x898, 0x4c42382f,
0x89c, 0x00656056,
0x8b0, 0x00000000,
0x8e0, 0x00000000,
0x8e4, 0x00000000,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90c, 0x31121311,
0xa00, 0x00d0c7d8,
0xa04, 0x811f0008,
0xa08, 0x80cd8300,
0xa0c, 0x2e62740f,
0xa10, 0x95009b78,
0xa14, 0x11145008,
0xa18, 0x00881117,
0xa1c, 0x89140fa0,
0xa20, 0x1a1b0000,
0xa24, 0x090e1317,
0xa28, 0x00000204,
0xa2c, 0x00000000,
0xc00, 0x00000040,
0xc04, 0x00005433,
0xc08, 0x000000e4,
0xc0c, 0x6c6c6c6c,
0xc10, 0x08800000,
0xc14, 0x40000100,
0xc18, 0x08000000,
0xc1c, 0x40000100,
0xc20, 0x08000000,
0xc24, 0x40000100,
0xc28, 0x08000000,
0xc2c, 0x40000100,
0xc30, 0x6de9ac44,
0xc34, 0x465c52cd,
0xc38, 0x497f5994,
0xc3c, 0x0a969764,
0xc40, 0x1f7c403f,
0xc44, 0x000100b7,
0xc48, 0xec020000,
0xc4c, 0x00000300,
0xc50, 0x69543420,
0xc54, 0x433c0094,
0xc58, 0x69543420,
0xc5c, 0x433c0094,
0xc60, 0x69543420,
0xc64, 0x433c0094,
0xc68, 0x69543420,
0xc6c, 0x433c0094,
0xc70, 0x2c7f000d,
0xc74, 0x0186175b,
0xc78, 0x0000001f,
0xc7c, 0x00b91612,
0xc80, 0x40000100,
0xc84, 0x20000000,
0xc88, 0x40000100,
0xc8c, 0x20200000,
0xc90, 0x40000100,
0xc94, 0x00000000,
0xc98, 0x40000100,
0xc9c, 0x00000000,
0xca0, 0x00492492,
0xca4, 0x00000000,
0xca8, 0x00000000,
0xcac, 0x00000000,
0xcb0, 0x00000000,
0xcb4, 0x00000000,
0xcb8, 0x00000000,
0xcbc, 0x00492492,
0xcc0, 0x00000000,
0xcc4, 0x00000000,
0xcc8, 0x00000000,
0xccc, 0x00000000,
0xcd0, 0x00000000,
0xcd4, 0x00000000,
0xcd8, 0x64b22427,
0xcdc, 0x00766932,
0xce0, 0x00222222,
0xd00, 0x00000750,
0xd04, 0x00000403,
0xd08, 0x0000907f,
0xd0c, 0x00000001,
0xd10, 0xa0633333,
0xd14, 0x33333c63,
0xd18, 0x6a8f5b6b,
0xd1c, 0x00000000,
0xd20, 0x00000000,
0xd24, 0x00000000,
0xd28, 0x00000000,
0xd2c, 0xcc979975,
0xd30, 0x00000000,
0xd34, 0x00000000,
0xd38, 0x00000000,
0xd3c, 0x00027293,
0xd40, 0x00000000,
0xd44, 0x00000000,
0xd48, 0x00000000,
0xd4c, 0x00000000,
0xd50, 0x6437140a,
0xd54, 0x024dbd02,
0xd58, 0x00000000,
0xd5c, 0x04032064,
0xe00, 0x161a1a1a,
0xe04, 0x12121416,
0xe08, 0x00001800,
0xe0c, 0x00000000,
0xe10, 0x161a1a1a,
0xe14, 0x12121416,
0xe18, 0x161a1a1a,
0xe1c, 0x12121416,
};
u32 Rtl8192UsbRadioA_Array[] = {
0x019, 0x00000003,
0x000, 0x000000bf,
0x001, 0x00000ee0,
0x002, 0x0000004c,
0x003, 0x000007f1,
0x004, 0x00000975,
0x005, 0x00000c58,
0x006, 0x00000ae6,
0x007, 0x000000ca,
0x008, 0x00000e1c,
0x009, 0x000007f0,
0x00a, 0x000009d0,
0x00b, 0x000001ba,
0x00c, 0x00000240,
0x00e, 0x00000020,
0x00f, 0x00000990,
0x012, 0x00000806,
0x014, 0x000005ab,
0x015, 0x00000f80,
0x016, 0x00000020,
0x017, 0x00000597,
0x018, 0x0000050a,
0x01a, 0x00000f80,
0x01b, 0x00000f5e,
0x01c, 0x00000008,
0x01d, 0x00000607,
0x01e, 0x000006cc,
0x01f, 0x00000000,
0x020, 0x000001a5,
0x01f, 0x00000001,
0x020, 0x00000165,
0x01f, 0x00000002,
0x020, 0x000000c6,
0x01f, 0x00000003,
0x020, 0x00000086,
0x01f, 0x00000004,
0x020, 0x00000046,
0x01f, 0x00000005,
0x020, 0x000001e6,
0x01f, 0x00000006,
0x020, 0x000001a6,
0x01f, 0x00000007,
0x020, 0x00000166,
0x01f, 0x00000008,
0x020, 0x000000c7,
0x01f, 0x00000009,
0x020, 0x00000087,
0x01f, 0x0000000a,
0x020, 0x000000f7,
0x01f, 0x0000000b,
0x020, 0x000000d7,
0x01f, 0x0000000c,
0x020, 0x000000b7,
0x01f, 0x0000000d,
0x020, 0x00000097,
0x01f, 0x0000000e,
0x020, 0x00000077,
0x01f, 0x0000000f,
0x020, 0x00000057,
0x01f, 0x00000010,
0x020, 0x00000037,
0x01f, 0x00000011,
0x020, 0x000000fb,
0x01f, 0x00000012,
0x020, 0x000000db,
0x01f, 0x00000013,
0x020, 0x000000bb,
0x01f, 0x00000014,
0x020, 0x000000ff,
0x01f, 0x00000015,
0x020, 0x000000e3,
0x01f, 0x00000016,
0x020, 0x000000c3,
0x01f, 0x00000017,
0x020, 0x000000a3,
0x01f, 0x00000018,
0x020, 0x00000083,
0x01f, 0x00000019,
0x020, 0x00000063,
0x01f, 0x0000001a,
0x020, 0x00000043,
0x01f, 0x0000001b,
0x020, 0x00000023,
0x01f, 0x0000001c,
0x020, 0x00000003,
0x01f, 0x0000001d,
0x020, 0x000001e3,
0x01f, 0x0000001e,
0x020, 0x000001c3,
0x01f, 0x0000001f,
0x020, 0x000001a3,
0x01f, 0x00000020,
0x020, 0x00000183,
0x01f, 0x00000021,
0x020, 0x00000163,
0x01f, 0x00000022,
0x020, 0x00000143,
0x01f, 0x00000023,
0x020, 0x00000123,
0x01f, 0x00000024,
0x020, 0x00000103,
0x023, 0x00000203,
0x024, 0x00000200,
0x00b, 0x000001ba,
0x02c, 0x000003d7,
0x02d, 0x00000ff0,
0x000, 0x00000037,
0x004, 0x00000160,
0x007, 0x00000080,
0x002, 0x0000088d,
0x0fe, 0x00000000,
0x0fe, 0x00000000,
0x016, 0x00000200,
0x016, 0x00000380,
0x016, 0x00000020,
0x016, 0x000001a0,
0x000, 0x000000bf,
0x00d, 0x0000001f,
0x00d, 0x00000c9f,
0x002, 0x0000004d,
0x000, 0x00000cbf,
0x004, 0x00000975,
0x007, 0x00000700,
};
u32 Rtl8192UsbRadioB_Array[] = {
0x019, 0x00000003,
0x000, 0x000000bf,
0x001, 0x000006e0,
0x002, 0x0000004c,
0x003, 0x000007f1,
0x004, 0x00000975,
0x005, 0x00000c58,
0x006, 0x00000ae6,
0x007, 0x000000ca,
0x008, 0x00000e1c,
0x000, 0x000000b7,
0x00a, 0x00000850,
0x000, 0x000000bf,
0x00b, 0x000001ba,
0x00c, 0x00000240,
0x00e, 0x00000020,
0x015, 0x00000f80,
0x016, 0x00000020,
0x017, 0x00000597,
0x018, 0x0000050a,
0x01a, 0x00000e00,
0x01b, 0x00000f5e,
0x01d, 0x00000607,
0x01e, 0x000006cc,
0x00b, 0x000001ba,
0x023, 0x00000203,
0x024, 0x00000200,
0x000, 0x00000037,
0x004, 0x00000160,
0x016, 0x00000200,
0x016, 0x00000380,
0x016, 0x00000020,
0x016, 0x000001a0,
0x00d, 0x00000ccc,
0x000, 0x000000bf,
0x002, 0x0000004d,
0x000, 0x00000cbf,
0x004, 0x00000975,
0x007, 0x00000700,
};
u32 Rtl8192UsbRadioC_Array[] = {
0x0, };
u32 Rtl8192UsbRadioD_Array[] = {
0x0, };
u32 Rtl8192UsbMACPHY_Array[] = {
0x03c, 0xffff0000, 0x00000f0f,
0x340, 0xffffffff, 0x161a1a1a,
0x344, 0xffffffff, 0x12121416,
0x348, 0x0000ffff, 0x00001818,
0x12c, 0xffffffff, 0x04000802,
0x318, 0x00000fff, 0x00000100,
};
u32 Rtl8192UsbMACPHY_Array_PG[] = {
0x03c, 0xffff0000, 0x00000f0f,
0xe00, 0xffffffff, 0x06090909,
0xe04, 0xffffffff, 0x00030306,
0xe08, 0x0000ff00, 0x00000000,
0xe10, 0xffffffff, 0x0a0c0d0f,
0xe14, 0xffffffff, 0x06070809,
0xe18, 0xffffffff, 0x0a0c0d0f,
0xe1c, 0xffffffff, 0x06070809,
0x12c, 0xffffffff, 0x04000802,
0x318, 0x00000fff, 0x00000800,
};
u32 Rtl8192UsbAGCTAB_Array[] = {
0xc78, 0x7d000001,
0xc78, 0x7d010001,
0xc78, 0x7d020001,
0xc78, 0x7d030001,
0xc78, 0x7d040001,
0xc78, 0x7d050001,
0xc78, 0x7c060001,
0xc78, 0x7b070001,
0xc78, 0x7a080001,
0xc78, 0x79090001,
0xc78, 0x780a0001,
0xc78, 0x770b0001,
0xc78, 0x760c0001,
0xc78, 0x750d0001,
0xc78, 0x740e0001,
0xc78, 0x730f0001,
0xc78, 0x72100001,
0xc78, 0x71110001,
0xc78, 0x70120001,
0xc78, 0x6f130001,
0xc78, 0x6e140001,
0xc78, 0x6d150001,
0xc78, 0x6c160001,
0xc78, 0x6b170001,
0xc78, 0x6a180001,
0xc78, 0x69190001,
0xc78, 0x681a0001,
0xc78, 0x671b0001,
0xc78, 0x661c0001,
0xc78, 0x651d0001,
0xc78, 0x641e0001,
0xc78, 0x491f0001,
0xc78, 0x48200001,
0xc78, 0x47210001,
0xc78, 0x46220001,
0xc78, 0x45230001,
0xc78, 0x44240001,
0xc78, 0x43250001,
0xc78, 0x28260001,
0xc78, 0x27270001,
0xc78, 0x26280001,
0xc78, 0x25290001,
0xc78, 0x242a0001,
0xc78, 0x232b0001,
0xc78, 0x222c0001,
0xc78, 0x212d0001,
0xc78, 0x202e0001,
0xc78, 0x0a2f0001,
0xc78, 0x08300001,
0xc78, 0x06310001,
0xc78, 0x05320001,
0xc78, 0x04330001,
0xc78, 0x03340001,
0xc78, 0x02350001,
0xc78, 0x01360001,
0xc78, 0x00370001,
0xc78, 0x00380001,
0xc78, 0x00390001,
0xc78, 0x003a0001,
0xc78, 0x003b0001,
0xc78, 0x003c0001,
0xc78, 0x003d0001,
0xc78, 0x003e0001,
0xc78, 0x003f0001,
0xc78, 0x7d400001,
0xc78, 0x7d410001,
0xc78, 0x7d420001,
0xc78, 0x7d430001,
0xc78, 0x7d440001,
0xc78, 0x7d450001,
0xc78, 0x7c460001,
0xc78, 0x7b470001,
0xc78, 0x7a480001,
0xc78, 0x79490001,
0xc78, 0x784a0001,
0xc78, 0x774b0001,
0xc78, 0x764c0001,
0xc78, 0x754d0001,
0xc78, 0x744e0001,
0xc78, 0x734f0001,
0xc78, 0x72500001,
0xc78, 0x71510001,
0xc78, 0x70520001,
0xc78, 0x6f530001,
0xc78, 0x6e540001,
0xc78, 0x6d550001,
0xc78, 0x6c560001,
0xc78, 0x6b570001,
0xc78, 0x6a580001,
0xc78, 0x69590001,
0xc78, 0x685a0001,
0xc78, 0x675b0001,
0xc78, 0x665c0001,
0xc78, 0x655d0001,
0xc78, 0x645e0001,
0xc78, 0x495f0001,
0xc78, 0x48600001,
0xc78, 0x47610001,
0xc78, 0x46620001,
0xc78, 0x45630001,
0xc78, 0x44640001,
0xc78, 0x43650001,
0xc78, 0x28660001,
0xc78, 0x27670001,
0xc78, 0x26680001,
0xc78, 0x25690001,
0xc78, 0x246a0001,
0xc78, 0x236b0001,
0xc78, 0x226c0001,
0xc78, 0x216d0001,
0xc78, 0x206e0001,
0xc78, 0x0a6f0001,
0xc78, 0x08700001,
0xc78, 0x06710001,
0xc78, 0x05720001,
0xc78, 0x04730001,
0xc78, 0x03740001,
0xc78, 0x02750001,
0xc78, 0x01760001,
0xc78, 0x00770001,
0xc78, 0x00780001,
0xc78, 0x00790001,
0xc78, 0x007a0001,
0xc78, 0x007b0001,
0xc78, 0x007c0001,
0xc78, 0x007d0001,
0xc78, 0x007e0001,
0xc78, 0x007f0001,
0xc78, 0x2e00001e,
0xc78, 0x2e01001e,
0xc78, 0x2e02001e,
0xc78, 0x2e03001e,
0xc78, 0x2e04001e,
0xc78, 0x2e05001e,
0xc78, 0x3006001e,
0xc78, 0x3407001e,
0xc78, 0x3908001e,
0xc78, 0x3c09001e,
0xc78, 0x3f0a001e,
0xc78, 0x420b001e,
0xc78, 0x440c001e,
0xc78, 0x450d001e,
0xc78, 0x460e001e,
0xc78, 0x460f001e,
0xc78, 0x4710001e,
0xc78, 0x4811001e,
0xc78, 0x4912001e,
0xc78, 0x4a13001e,
0xc78, 0x4b14001e,
0xc78, 0x4b15001e,
0xc78, 0x4c16001e,
0xc78, 0x4d17001e,
0xc78, 0x4e18001e,
0xc78, 0x4f19001e,
0xc78, 0x4f1a001e,
0xc78, 0x501b001e,
0xc78, 0x511c001e,
0xc78, 0x521d001e,
0xc78, 0x521e001e,
0xc78, 0x531f001e,
0xc78, 0x5320001e,
0xc78, 0x5421001e,
0xc78, 0x5522001e,
0xc78, 0x5523001e,
0xc78, 0x5624001e,
0xc78, 0x5725001e,
0xc78, 0x5726001e,
0xc78, 0x5827001e,
0xc78, 0x5828001e,
0xc78, 0x5929001e,
0xc78, 0x592a001e,
0xc78, 0x5a2b001e,
0xc78, 0x5b2c001e,
0xc78, 0x5c2d001e,
0xc78, 0x5c2e001e,
0xc78, 0x5d2f001e,
0xc78, 0x5e30001e,
0xc78, 0x5f31001e,
0xc78, 0x6032001e,
0xc78, 0x6033001e,
0xc78, 0x6134001e,
0xc78, 0x6235001e,
0xc78, 0x6336001e,
0xc78, 0x6437001e,
0xc78, 0x6438001e,
0xc78, 0x6539001e,
0xc78, 0x663a001e,
0xc78, 0x673b001e,
0xc78, 0x673c001e,
0xc78, 0x683d001e,
0xc78, 0x693e001e,
0xc78, 0x6a3f001e,
};

View File

@ -1,26 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef IMG_H
#define IMG_H
#define MACPHY_Array_PGLength 30
#define PHY_REG_1T2RArrayLength 296
#define AGCTAB_ArrayLength 384
#define MACPHY_ArrayLength 18
#define RadioA_ArrayLength 246
#define RadioB_ArrayLength 78
#define RadioC_ArrayLength 1
#define RadioD_ArrayLength 1
#define PHY_REGArrayLength 1
extern u32 Rtl8192UsbPHY_REGArray[];
extern u32 Rtl8192UsbPHY_REG_1T2RArray[];
extern u32 Rtl8192UsbRadioA_Array[];
extern u32 Rtl8192UsbRadioB_Array[];
extern u32 Rtl8192UsbRadioC_Array[];
extern u32 Rtl8192UsbRadioD_Array[];
extern u32 Rtl8192UsbMACPHY_Array[];
extern u32 Rtl8192UsbMACPHY_Array_PG[];
extern u32 Rtl8192UsbAGCTAB_Array[];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _R819XU_PHY_H
#define _R819XU_PHY_H
/* Channel switch: The size of command tables for switch channel */
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
enum baseband_config_type {
BASEBAND_CONFIG_PHY_REG = 0, //Radio Path A
BASEBAND_CONFIG_AGC_TAB = 1, //Radio Path B
};
enum switch_chan_cmd_id {
CMD_ID_END,
CMD_ID_SET_TX_PWR_LEVEL,
CMD_ID_WRITE_PORT_ULONG,
CMD_ID_WRITE_PORT_USHORT,
CMD_ID_WRITE_PORT_UCHAR,
CMD_ID_RF_WRITE_REG,
};
/* -----------------------Define structure---------------------- */
/* 1. Switch channel related */
struct sw_chnl_cmd {
enum switch_chan_cmd_id cmd_id;
u32 para_1;
u32 para_2;
u32 ms_delay;
} __packed;
enum hw90_block_e {
HW90_BLOCK_MAC = 0,
HW90_BLOCK_PHY0 = 1,
HW90_BLOCK_PHY1 = 2,
HW90_BLOCK_RF = 3,
HW90_BLOCK_MAXIMUM = 4, /* Never use this */
};
enum rf90_radio_path_e {
RF90_PATH_A = 0, /* Radio Path A */
RF90_PATH_B = 1, /* Radio Path B */
RF90_PATH_C = 2, /* Radio Path C */
RF90_PATH_D = 3, /* Radio Path D */
RF90_PATH_MAX /* Max RF number 92 support */
};
u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 e_rfpath);
void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr,
u32 bitmask, u32 data);
u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr, u32 bitmask);
void rtl8192_phy_SetRFReg(struct net_device *dev,
enum rf90_radio_path_e e_rfpath,
u32 reg_addr, u32 bitmask, u32 data);
u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
enum rf90_radio_path_e e_rfpath,
u32 reg_addr, u32 bitmask);
void rtl8192_phy_configmac(struct net_device *dev);
u8 rtl8192_phy_checkBBAndRF(struct net_device *dev,
enum hw90_block_e CheckBlock,
enum rf90_radio_path_e e_rfpath);
void rtl8192_BBConfig(struct net_device *dev);
void rtl8192_phy_getTxPower(struct net_device *dev);
void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
void rtl8192_phy_RFConfig(struct net_device *dev);
void rtl8192_phy_updateInitGain(struct net_device *dev);
u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
enum rf90_radio_path_e e_rfpath);
u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
void rtl8192_SetBWMode(struct net_device *dev,
enum ht_channel_width bandwidth,
enum ht_extension_chan_offset offset);
void rtl8192_SwChnl_WorkItem(struct net_device *dev);
void rtl8192_SetBWModeWorkItem(struct net_device *dev);
void InitialGain819xUsb(struct net_device *dev, u8 Operation);
void InitialGainOperateWorkItemCallBack(struct work_struct *work);
#endif

View File

@ -1,143 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _R819XU_PHYREG_H
#define _R819XU_PHYREG_H
#define RF_DATA 0x1d4 /* FW will write RF data in the register.*/
/* page8 */
#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC */
#define rFPGA0_TxGainStage 0x80c
#define rFPGA0_XA_HSSIParameter1 0x820
#define rFPGA0_XA_HSSIParameter2 0x824
#define rFPGA0_XB_HSSIParameter1 0x828
#define rFPGA0_XB_HSSIParameter2 0x82c
#define rFPGA0_XC_HSSIParameter1 0x830
#define rFPGA0_XC_HSSIParameter2 0x834
#define rFPGA0_XD_HSSIParameter1 0x838
#define rFPGA0_XD_HSSIParameter2 0x83c
#define rFPGA0_XA_LSSIParameter 0x840
#define rFPGA0_XB_LSSIParameter 0x844
#define rFPGA0_XC_LSSIParameter 0x848
#define rFPGA0_XD_LSSIParameter 0x84c
#define rFPGA0_XAB_SwitchControl 0x858
#define rFPGA0_XCD_SwitchControl 0x85c
#define rFPGA0_XA_RFInterfaceOE 0x860
#define rFPGA0_XB_RFInterfaceOE 0x864
#define rFPGA0_XC_RFInterfaceOE 0x868
#define rFPGA0_XD_RFInterfaceOE 0x86c
#define rFPGA0_XAB_RFInterfaceSW 0x870
#define rFPGA0_XCD_RFInterfaceSW 0x874
#define rFPGA0_XAB_RFParameter 0x878
#define rFPGA0_XCD_RFParameter 0x87c
#define rFPGA0_AnalogParameter1 0x880
#define rFPGA0_AnalogParameter4 0x88c
#define rFPGA0_XA_LSSIReadBack 0x8a0
#define rFPGA0_XB_LSSIReadBack 0x8a4
#define rFPGA0_XC_LSSIReadBack 0x8a8
#define rFPGA0_XD_LSSIReadBack 0x8ac
#define rFPGA0_XAB_RFInterfaceRB 0x8e0
#define rFPGA0_XCD_RFInterfaceRB 0x8e4
/* page 9 */
#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC */
/* page a */
#define rCCK0_System 0xa00
#define rCCK0_AFESetting 0xa04
#define rCCK0_CCA 0xa08
#define rCCK0_TxFilter1 0xa20
#define rCCK0_TxFilter2 0xa24
#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
/* page c */
#define rOFDM0_TRxPathEnable 0xc04
#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */
#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
#define rOFDM0_XBRxAFE 0xc18
#define rOFDM0_XBRxIQImbalance 0xc1c
#define rOFDM0_XCRxAFE 0xc20
#define rOFDM0_XCRxIQImbalance 0xc24
#define rOFDM0_XDRxAFE 0xc28
#define rOFDM0_XDRxIQImbalance 0xc2c
#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD */
#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync.*/
#define rOFDM0_RxDetector3 0xc38 /* Frame Sync.*/
#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
#define rOFDM0_XAAGCCore1 0xc50
#define rOFDM0_XAAGCCore2 0xc54
#define rOFDM0_XBAGCCore1 0xc58
#define rOFDM0_XBAGCCore2 0xc5c
#define rOFDM0_XCAGCCore1 0xc60
#define rOFDM0_XCAGCCore2 0xc64
#define rOFDM0_XDAGCCore1 0xc68
#define rOFDM0_XDAGCCore2 0xc6c
#define rOFDM0_XATxIQImbalance 0xc80
#define rOFDM0_XATxAFE 0xc84
#define rOFDM0_XBTxIQImbalance 0xc88
#define rOFDM0_XBTxAFE 0xc8c
#define rOFDM0_XCTxIQImbalance 0xc90
#define rOFDM0_XCTxAFE 0xc94
#define rOFDM0_XDTxIQImbalance 0xc98
#define rOFDM0_XDTxAFE 0xc9c
/* page d */
#define rOFDM1_LSTF 0xd00
#define rOFDM1_TRxPathEnable 0xd04
/* page e */
#define rTxAGC_Rate18_06 0xe00
#define rTxAGC_Rate54_24 0xe04
#define rTxAGC_CCK_Mcs32 0xe08
#define rTxAGC_Mcs03_Mcs00 0xe10
#define rTxAGC_Mcs07_Mcs04 0xe14
#define rTxAGC_Mcs11_Mcs08 0xe18
#define rTxAGC_Mcs15_Mcs12 0xe1c
/* RF
* Zebra1
*/
#define rZebra1_Channel 0x7
/* Zebra4 */
#define rGlobalCtrl 0
/* Bit Mask
* page-8
*/
#define bRFMOD 0x1
#define bCCKEn 0x1000000
#define bOFDMEn 0x2000000
#define bXBTxAGC 0xf00
#define bXCTxAGC 0xf000
#define b3WireDataLength 0x800
#define b3WireAddressLength 0x400
#define bRFSI_RFENV 0x10
#define bLSSIReadAddress 0x3f000000 /* LSSI "Read" Address */
#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
#define bLSSIReadBackData 0xfff
#define bXtalCap 0x0f000000
/* page-a */
#define bCCKSideBand 0x10
/* page e */
#define bTxAGCRateCCK 0x7f00
/* RF
* Zebra1
*/
#define bZebra1_ChannelNum 0xf80
/* RTL8258 */
/* for PutRegsetting & GetRegSetting BitMask */
#define bMaskByte0 0xff
#define bMaskByte1 0xff00
#define bMaskByte2 0xff0000
#define bMaskHWord 0xffff0000
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
/* for PutRFRegsetting & GetRFRegSetting BitMask */
#define bMask12Bits 0xfff
#endif /* __INC_HAL8190PCIPHYREG_H */