staging driver fixes for 3.15-rc2
Here are a few staging driver fixes for issues that have been reported for 3.15-rc2. Also dominating the diffstat for the pull request is the removal of the rtl8187se driver. It's no longer needed in staging as a "real" driver for this hardware is now merged in the tree in the "correct" location in drivers/net/ All of these patches have been tested in linux-next. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlNRmSwACgkQMUfUDdst+ympmwCgmht0boH4QJSf8ojnkrgXhZOG JUsAoJqfC22c/dKfLbMgXYuU12Kuidhe =poU3 -----END PGP SIGNATURE----- Merge tag 'staging-3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging driver fixes from Greg KH: "Here are a few staging driver fixes for issues that have been reported for 3.15-rc2. Also dominating the diffstat for the pull request is the removal of the rtl8187se driver. It's no longer needed in staging as a "real" driver for this hardware is now merged in the tree in the "correct" location in drivers/net/ All of these patches have been tested in linux-next" * tag 'staging-3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: staging: r8188eu: Fix case where ethtype was never obtained and always be checked against 0 staging: r8712u: Fix case where ethtype was never obtained and always be checked against 0 staging: r8188eu: Calling rtw_get_stainfo() with a NULL sta_addr will return NULL staging: comedi: fix circular locking dependency in comedi_mmap() staging: r8723au: Add missing initialization of change_inx in sort algorithm Staging: unisys: use after free in list_for_each() staging: unisys: use after free in error messages staging: speakup: fix misuse of kstrtol() in handle_goto() staging: goldfish: Call free_irq in error path staging: delete rtl8187se wireless driver staging: rtl8723au: Fix buffer overflow in rtw_get_wfd_ie() staging: gs_fpgaboot: remove __TIMESTAMP__ macro staging: vme: fix memory leak in vme_user_probe() staging: fpgaboot: clean up Makefile staging/usbip: fix store_attach() sscanf return value check staging/usbip: userspace - fix usbipd SIGSEGV from refresh_exported_devices() staging: rtl8188eu: remove spaces, correct counts to unbreak P2P ioctls staging/rtl8821ae: Fix OOM handling in _rtl_init_deferred_work()
This commit is contained in:
commit
8cb652bb10
|
@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig"
|
|||
|
||||
source "drivers/staging/panel/Kconfig"
|
||||
|
||||
source "drivers/staging/rtl8187se/Kconfig"
|
||||
|
||||
source "drivers/staging/rtl8192u/Kconfig"
|
||||
|
||||
source "drivers/staging/rtl8192e/Kconfig"
|
||||
|
|
|
@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/
|
|||
obj-$(CONFIG_COMEDI) += comedi/
|
||||
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
|
||||
obj-$(CONFIG_PANEL) += panel/
|
||||
obj-$(CONFIG_R8187SE) += rtl8187se/
|
||||
obj-$(CONFIG_RTL8192U) += rtl8192u/
|
||||
obj-$(CONFIG_RTL8192E) += rtl8192e/
|
||||
obj-$(CONFIG_R8712U) += rtl8712/
|
||||
|
|
|
@ -61,6 +61,8 @@ static void __comedi_buf_free(struct comedi_device *dev,
|
|||
struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_buf_map *bm;
|
||||
unsigned long flags;
|
||||
|
||||
if (async->prealloc_buf) {
|
||||
vunmap(async->prealloc_buf);
|
||||
|
@ -68,8 +70,11 @@ static void __comedi_buf_free(struct comedi_device *dev,
|
|||
async->prealloc_bufsz = 0;
|
||||
}
|
||||
|
||||
comedi_buf_map_put(async->buf_map);
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
bm = async->buf_map;
|
||||
async->buf_map = NULL;
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
comedi_buf_map_put(bm);
|
||||
}
|
||||
|
||||
static void __comedi_buf_alloc(struct comedi_device *dev,
|
||||
|
@ -80,6 +85,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
|||
struct page **pages = NULL;
|
||||
struct comedi_buf_map *bm;
|
||||
struct comedi_buf_page *buf;
|
||||
unsigned long flags;
|
||||
unsigned i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
|
||||
|
@ -92,8 +98,10 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
|||
if (!bm)
|
||||
return;
|
||||
|
||||
async->buf_map = bm;
|
||||
kref_init(&bm->refcount);
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
async->buf_map = bm;
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
bm->dma_dir = s->async_dma_dir;
|
||||
if (bm->dma_dir != DMA_NONE)
|
||||
/* Need ref to hardware device to free buffer later. */
|
||||
|
@ -127,7 +135,9 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
|||
|
||||
pages[i] = virt_to_page(buf->virt_addr);
|
||||
}
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
bm->n_pages = i;
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
|
||||
/* vmap the prealloc_buf if all the pages were allocated */
|
||||
if (i == n_pages)
|
||||
|
@ -150,6 +160,29 @@ int comedi_buf_map_put(struct comedi_buf_map *bm)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* returns s->async->buf_map and increments its kref refcount */
|
||||
struct comedi_buf_map *
|
||||
comedi_buf_map_from_subdev_get(struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_buf_map *bm = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (!async)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
bm = async->buf_map;
|
||||
/* only want it if buffer pages allocated */
|
||||
if (bm && bm->n_pages)
|
||||
comedi_buf_map_get(bm);
|
||||
else
|
||||
bm = NULL;
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
|
||||
return bm;
|
||||
}
|
||||
|
||||
bool comedi_buf_is_mmapped(struct comedi_async *async)
|
||||
{
|
||||
struct comedi_buf_map *bm = async->buf_map;
|
||||
|
|
|
@ -1926,14 +1926,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
struct comedi_device *dev = file->private_data;
|
||||
struct comedi_subdevice *s;
|
||||
struct comedi_async *async;
|
||||
struct comedi_buf_map *bm;
|
||||
struct comedi_buf_map *bm = NULL;
|
||||
unsigned long start = vma->vm_start;
|
||||
unsigned long size;
|
||||
int n_pages;
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
/*
|
||||
* 'trylock' avoids circular dependency with current->mm->mmap_sem
|
||||
* and down-reading &dev->attach_lock should normally succeed without
|
||||
* contention unless the device is in the process of being attached
|
||||
* or detached.
|
||||
*/
|
||||
if (!down_read_trylock(&dev->attach_lock))
|
||||
return -EAGAIN;
|
||||
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
|
@ -1973,7 +1980,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
}
|
||||
|
||||
n_pages = size >> PAGE_SHIFT;
|
||||
bm = async->buf_map;
|
||||
|
||||
/* get reference to current buf map (if any) */
|
||||
bm = comedi_buf_map_from_subdev_get(s);
|
||||
if (!bm || n_pages > bm->n_pages) {
|
||||
retval = -EINVAL;
|
||||
goto done;
|
||||
|
@ -1997,7 +2006,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
|
||||
retval = 0;
|
||||
done:
|
||||
mutex_unlock(&dev->mutex);
|
||||
up_read(&dev->attach_lock);
|
||||
comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ void comedi_buf_reset(struct comedi_async *async);
|
|||
bool comedi_buf_is_mmapped(struct comedi_async *async);
|
||||
void comedi_buf_map_get(struct comedi_buf_map *bm);
|
||||
int comedi_buf_map_put(struct comedi_buf_map *bm);
|
||||
struct comedi_buf_map *comedi_buf_map_from_subdev_get(
|
||||
struct comedi_subdevice *s);
|
||||
unsigned int comedi_buf_write_n_allocated(struct comedi_async *async);
|
||||
void comedi_device_cancel_all(struct comedi_device *dev);
|
||||
|
||||
|
|
|
@ -334,6 +334,7 @@ static int goldfish_audio_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_misc_register_failed:
|
||||
free_irq(data->irq, data);
|
||||
err_request_irq_failed:
|
||||
dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
|
||||
data->buffer_virt, data->buffer_phys);
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
gs_fpga-y += gs_fpgaboot.o io.o
|
||||
obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o
|
||||
|
||||
ccflags-$(CONFIG_GS_FPGA_DEBUG) := -DDEBUG
|
||||
|
|
|
@ -373,7 +373,6 @@ static int __init gs_fpgaboot_init(void)
|
|||
r = -1;
|
||||
|
||||
pr_info("FPGA DOWNLOAD --->\n");
|
||||
pr_info("built at %s UTC\n", __TIMESTAMP__);
|
||||
|
||||
pr_info("FPGA image file name: %s\n", file);
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
config R8187SE
|
||||
tristate "RealTek RTL8187SE Wireless LAN NIC driver"
|
||||
depends on PCI && WLAN
|
||||
depends on m
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select EEPROM_93CX6
|
||||
select CRYPTO
|
||||
---help---
|
||||
If built as a module, it will be called r8187se.ko.
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y
|
||||
#ccflags-y += -std=gnu89
|
||||
#ccflags-y += -O2
|
||||
#CC = gcc
|
||||
|
||||
ccflags-y := -DSW_ANTE
|
||||
ccflags-y += -DTX_TRACK
|
||||
ccflags-y += -DHIGH_POWER
|
||||
ccflags-y += -DSW_DIG
|
||||
ccflags-y += -DRATE_ADAPT
|
||||
|
||||
#enable it for legacy power save, disable it for leisure power save
|
||||
ccflags-y += -DENABLE_LPS
|
||||
|
||||
|
||||
#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
|
||||
|
||||
r8187se-y := \
|
||||
r8180_core.o \
|
||||
r8180_wx.o \
|
||||
r8180_rtl8225z2.o \
|
||||
r8185b_init.o \
|
||||
r8180_dm.o \
|
||||
ieee80211/dot11d.o \
|
||||
ieee80211/ieee80211_softmac.o \
|
||||
ieee80211/ieee80211_rx.o \
|
||||
ieee80211/ieee80211_tx.o \
|
||||
ieee80211/ieee80211_wx.o \
|
||||
ieee80211/ieee80211_module.o \
|
||||
ieee80211/ieee80211_softmac_wx.o \
|
||||
ieee80211/ieee80211_crypt.o \
|
||||
ieee80211/ieee80211_crypt_tkip.o \
|
||||
ieee80211/ieee80211_crypt_ccmp.o \
|
||||
ieee80211/ieee80211_crypt_wep.o
|
||||
|
||||
obj-$(CONFIG_R8187SE) += r8187se.o
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
TODO:
|
||||
- prepare private ieee80211 stack for merge with rtl8192su's version:
|
||||
- add hwsec_active flag to struct ieee80211_device
|
||||
- add bHwSec flag to cb_desc structure
|
||||
- switch to use shared "librtl" instead of private ieee80211 stack
|
||||
- switch to use LIB80211
|
||||
- switch to use MAC80211
|
||||
- use kernel coding style
|
||||
- checkpatch.pl fixes
|
||||
- sparse fixes
|
||||
- integrate with drivers/net/wireless/rtl818x
|
||||
|
||||
Please send any patches to Greg Kroah-Hartman <greg@kroah.com>.
|
|
@ -1,189 +0,0 @@
|
|||
#include "dot11d.h"
|
||||
|
||||
void Dot11d_Init(struct ieee80211_device *ieee)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
|
||||
|
||||
pDot11dInfo->bEnabled = 0;
|
||||
|
||||
pDot11dInfo->State = DOT11D_STATE_NONE;
|
||||
pDot11dInfo->CountryIeLen = 0;
|
||||
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
|
||||
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
|
||||
RESET_CIE_WATCHDOG(ieee);
|
||||
|
||||
netdev_info(ieee->dev, "Dot11d_Init()\n");
|
||||
}
|
||||
|
||||
/* Reset to the state as we are just entering a regulatory domain. */
|
||||
void Dot11d_Reset(struct ieee80211_device *ieee)
|
||||
{
|
||||
u32 i;
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
|
||||
|
||||
/* Clear old channel map */
|
||||
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
|
||||
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
|
||||
/* Set new channel map */
|
||||
for (i = 1; i <= 11; i++)
|
||||
(pDot11dInfo->channel_map)[i] = 1;
|
||||
|
||||
for (i = 12; i <= 14; i++)
|
||||
(pDot11dInfo->channel_map)[i] = 2;
|
||||
|
||||
pDot11dInfo->State = DOT11D_STATE_NONE;
|
||||
pDot11dInfo->CountryIeLen = 0;
|
||||
RESET_CIE_WATCHDOG(ieee);
|
||||
}
|
||||
|
||||
/*
|
||||
* Description:
|
||||
* Update country IE from Beacon or Probe Response 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_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
|
||||
u16 CoutryIeLen, u8 *pCoutryIe)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
|
||||
u8 i, j, NumTriples, MaxChnlNum;
|
||||
u8 index, MaxTxPowerInDbm;
|
||||
PCHNL_TXPOWER_TRIPLE pTriple;
|
||||
|
||||
if ((CoutryIeLen - 3)%3 != 0) {
|
||||
netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
|
||||
Dot11d_Reset(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
|
||||
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
|
||||
MaxChnlNum = 0;
|
||||
NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
|
||||
pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
|
||||
for (i = 0; i < NumTriples; i++) {
|
||||
if (MaxChnlNum >= pTriple->FirstChnl) {
|
||||
/*
|
||||
* It is not in a monotonically increasing order,
|
||||
* so stop processing.
|
||||
*/
|
||||
netdev_info(dev->dev,
|
||||
"Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
|
||||
Dot11d_Reset(dev);
|
||||
return;
|
||||
}
|
||||
if (MAX_CHANNEL_NUMBER <
|
||||
(pTriple->FirstChnl + pTriple->NumChnls)) {
|
||||
/*
|
||||
* It is not a valid set of channel id,
|
||||
* so stop processing
|
||||
*/
|
||||
netdev_info(dev->dev,
|
||||
"Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
|
||||
Dot11d_Reset(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < pTriple->NumChnls; j++) {
|
||||
index = pTriple->FirstChnl + j;
|
||||
pDot11dInfo->channel_map[index] = 1;
|
||||
MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm;
|
||||
pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm;
|
||||
MaxChnlNum = pTriple->FirstChnl + j;
|
||||
}
|
||||
|
||||
pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
|
||||
}
|
||||
#if 1
|
||||
netdev_info(dev->dev, "Channel List:");
|
||||
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
|
||||
if (pDot11dInfo->channel_map[i] > 0)
|
||||
netdev_info(dev->dev, " %d", i);
|
||||
netdev_info(dev->dev, "\n");
|
||||
#endif
|
||||
|
||||
UPDATE_CIE_SRC(dev, pTaddr);
|
||||
|
||||
pDot11dInfo->CountryIeLen = CoutryIeLen;
|
||||
memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
|
||||
pDot11dInfo->State = DOT11D_STATE_LEARNED;
|
||||
}
|
||||
|
||||
u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
|
||||
u8 MaxTxPwrInDbm = 255;
|
||||
|
||||
if (MAX_CHANNEL_NUMBER < Channel) {
|
||||
netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
|
||||
return MaxTxPwrInDbm;
|
||||
}
|
||||
if (pDot11dInfo->channel_map[Channel])
|
||||
MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
|
||||
|
||||
return MaxTxPwrInDbm;
|
||||
}
|
||||
|
||||
|
||||
void DOT11D_ScanComplete(struct ieee80211_device *dev)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
|
||||
|
||||
switch (pDot11dInfo->State) {
|
||||
case DOT11D_STATE_LEARNED:
|
||||
pDot11dInfo->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;
|
||||
}
|
||||
}
|
||||
|
||||
int IsLegalChannel(struct ieee80211_device *dev, u8 channel)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
|
||||
|
||||
if (MAX_CHANNEL_NUMBER < channel) {
|
||||
netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
|
||||
return 0;
|
||||
}
|
||||
if (pDot11dInfo->channel_map[channel] > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ToLegalChannel(struct ieee80211_device *dev, u8 channel)
|
||||
{
|
||||
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
|
||||
u8 default_chn = 0;
|
||||
u32 i = 0;
|
||||
|
||||
for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
|
||||
if (pDot11dInfo->channel_map[i] > 0) {
|
||||
default_chn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MAX_CHANNEL_NUMBER < channel) {
|
||||
netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
|
||||
return default_chn;
|
||||
}
|
||||
|
||||
if (pDot11dInfo->channel_map[channel] > 0)
|
||||
return channel;
|
||||
|
||||
return default_chn;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
#ifndef __INC_DOT11D_H
|
||||
#define __INC_DOT11D_H
|
||||
|
||||
#include "ieee80211.h"
|
||||
|
||||
/* #define ENABLE_DOT11D */
|
||||
|
||||
/* #define DOT11D_MAX_CHNL_NUM 83 */
|
||||
|
||||
typedef struct _CHNL_TXPOWER_TRIPLE {
|
||||
u8 FirstChnl;
|
||||
u8 NumChnls;
|
||||
u8 MaxTxPowerInDbm;
|
||||
} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
|
||||
|
||||
typedef enum _DOT11D_STATE {
|
||||
DOT11D_STATE_NONE = 0,
|
||||
DOT11D_STATE_LEARNED,
|
||||
DOT11D_STATE_DONE,
|
||||
} DOT11D_STATE;
|
||||
|
||||
typedef struct _RT_DOT11D_INFO {
|
||||
/* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */
|
||||
|
||||
bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
|
||||
|
||||
u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
|
||||
u8 CountryIeBuf[MAX_IE_LEN];
|
||||
u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */
|
||||
u8 CountryIeWatchdog;
|
||||
|
||||
u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
|
||||
/* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */
|
||||
/* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */
|
||||
u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
|
||||
|
||||
DOT11D_STATE State;
|
||||
} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
|
||||
|
||||
#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0)
|
||||
#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
|
||||
#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
|
||||
|
||||
#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
|
||||
#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
|
||||
|
||||
#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
|
||||
#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
|
||||
|
||||
#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
|
||||
(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
|
||||
FALSE : \
|
||||
(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
|
||||
|
||||
#define CIE_WATCHDOG_TH 1
|
||||
#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
|
||||
#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
|
||||
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
|
||||
|
||||
#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
|
||||
|
||||
void Dot11d_Init(struct ieee80211_device *dev);
|
||||
void Dot11d_Reset(struct ieee80211_device *dev);
|
||||
void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
|
||||
u16 CoutryIeLen, u8 *pCoutryIe);
|
||||
u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel);
|
||||
void DOT11D_ScanComplete(struct ieee80211_device *dev);
|
||||
int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
|
||||
int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
|
||||
|
||||
#endif /* #ifndef __INC_DOT11D_H */
|
File diff suppressed because it is too large
Load diff
|
@ -1,240 +0,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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See README and COPYING for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
//#include <linux/config.h>
|
||||
#include <linux/module.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(unsigned long data)
|
||||
{
|
||||
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
ieee80211_crypt_deinit_entries(ieee, 0);
|
||||
if (!list_empty(&ieee->crypt_deinit_list)) {
|
||||
pr_debug("entries remaining in delayed crypt deletion list\n");
|
||||
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 == NULL)
|
||||
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 == NULL)
|
||||
return -1;
|
||||
|
||||
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
|
||||
if (alg == NULL)
|
||||
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("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 == NULL)
|
||||
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("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 == NULL)
|
||||
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;
|
||||
else
|
||||
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 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;
|
||||
struct ieee80211_crypto_alg *alg = NULL;
|
||||
|
||||
if (hcrypt == NULL)
|
||||
return;
|
||||
|
||||
list_for_each_safe(ptr, n, &hcrypt->algs) {
|
||||
alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
|
||||
if (alg) {
|
||||
list_del(ptr);
|
||||
pr_debug("unregistered algorithm '%s' (deinit)\n",
|
||||
alg->ops->name);
|
||||
kfree(alg);
|
||||
}
|
||||
}
|
||||
kfree(hcrypt);
|
||||
}
|
|
@ -1,86 +0,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 program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See README and COPYING for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 *, int);
|
||||
void ieee80211_crypt_deinit_handler(unsigned long);
|
||||
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
|
||||
struct ieee80211_crypt_data **crypt);
|
||||
|
||||
#endif
|
|
@ -1,455 +0,0 @@
|
|||
/*
|
||||
* Host AP crypt: host-based CCMP encryption implementation for Host AP driver
|
||||
*
|
||||
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See README and COPYING for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.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 <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_tfm *tfm;
|
||||
|
||||
/* scratch buffers for virt_to_page() (crypto API) */
|
||||
u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
|
||||
tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
|
||||
u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
|
||||
};
|
||||
|
||||
static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
|
||||
const u8 pt[16], u8 ct[16])
|
||||
{
|
||||
crypto_cipher_encrypt_one((void *)tfm, ct, pt);
|
||||
}
|
||||
|
||||
static void *ieee80211_ccmp_init(int key_idx)
|
||||
{
|
||||
struct ieee80211_ccmp_data *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||
if (priv == NULL)
|
||||
goto fail;
|
||||
priv->key_idx = key_idx;
|
||||
|
||||
priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(priv->tfm)) {
|
||||
pr_debug("could not allocate crypto API aes\n");
|
||||
priv->tfm = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return priv;
|
||||
|
||||
fail:
|
||||
if (priv) {
|
||||
if (priv->tfm)
|
||||
crypto_free_cipher((void *)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_cipher((void *)_priv->tfm);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
|
||||
static inline void xor_block(u8 *b, u8 *a, size_t len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
b[i] ^= a[i];
|
||||
}
|
||||
|
||||
static void ccmp_init_blocks(struct crypto_tfm *tfm,
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
u8 *pn, size_t dlen, u8 *b0, u8 *auth,
|
||||
u8 *s0)
|
||||
{
|
||||
u8 *pos, qc = 0;
|
||||
size_t aad_len;
|
||||
u16 fc;
|
||||
int a4_included, qc_included;
|
||||
u8 aad[2 * AES_BLOCK_LEN];
|
||||
|
||||
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));
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/* CCM Initial Block:
|
||||
* Flag (Include authentication header, M=3 (8-octet MIC),
|
||||
* L=1 (2-octet Dlen))
|
||||
* Nonce: 0x00 | A2 | PN
|
||||
* Dlen */
|
||||
b0[0] = 0x59;
|
||||
b0[1] = qc;
|
||||
memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
|
||||
memcpy(b0 + 8, pn, CCMP_PN_LEN);
|
||||
b0[14] = (dlen >> 8) & 0xff;
|
||||
b0[15] = dlen & 0xff;
|
||||
|
||||
/* 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] = 0; /* aad_len >> 8 */
|
||||
aad[1] = aad_len & 0xff;
|
||||
aad[2] = pos[0] & 0x8f;
|
||||
aad[3] = pos[1] & 0xc7;
|
||||
memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
|
||||
pos = (u8 *) &hdr->seq_ctl;
|
||||
aad[22] = pos[0] & 0x0f;
|
||||
aad[23] = 0; /* all bits masked */
|
||||
memset(aad + 24, 0, 8);
|
||||
if (a4_included)
|
||||
memcpy(aad + 24, hdr->addr4, ETH_ALEN);
|
||||
if (qc_included) {
|
||||
aad[a4_included ? 30 : 24] = qc;
|
||||
/* rest of QC masked */
|
||||
}
|
||||
|
||||
/* Start with the first block and AAD */
|
||||
ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
|
||||
xor_block(auth, aad, AES_BLOCK_LEN);
|
||||
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
|
||||
xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
|
||||
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
|
||||
b0[0] &= 0x07;
|
||||
b0[14] = b0[15] = 0;
|
||||
ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
|
||||
}
|
||||
|
||||
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
{
|
||||
struct ieee80211_ccmp_data *key = priv;
|
||||
int data_len, i;
|
||||
u8 *pos;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
int blocks, last, len;
|
||||
u8 *mic;
|
||||
u8 *b0 = key->tx_b0;
|
||||
u8 *b = key->tx_b;
|
||||
u8 *e = key->tx_e;
|
||||
u8 *s0 = key->tx_s0;
|
||||
|
||||
if (skb_headroom(skb) < CCMP_HDR_LEN ||
|
||||
skb_tailroom(skb) < CCMP_MIC_LEN ||
|
||||
skb->len < hdr_len)
|
||||
return -1;
|
||||
|
||||
data_len = skb->len - hdr_len;
|
||||
pos = skb_push(skb, CCMP_HDR_LEN);
|
||||
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
|
||||
pos += hdr_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) | (1 << 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 ieee80211_hdr_4addr *)skb->data;
|
||||
mic = skb_put(skb, CCMP_MIC_LEN);
|
||||
|
||||
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
|
||||
|
||||
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
|
||||
last = data_len % AES_BLOCK_LEN;
|
||||
|
||||
for (i = 1; i <= blocks; i++) {
|
||||
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
|
||||
/* Authentication */
|
||||
xor_block(b, pos, len);
|
||||
ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
|
||||
/* Encryption, with counter */
|
||||
b0[14] = (i >> 8) & 0xff;
|
||||
b0[15] = i & 0xff;
|
||||
ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
|
||||
xor_block(pos, e, len);
|
||||
pos += len;
|
||||
}
|
||||
|
||||
for (i = 0; i < CCMP_MIC_LEN; i++)
|
||||
mic[i] = b[i] ^ s0[i];
|
||||
|
||||
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 ieee80211_hdr_4addr *hdr;
|
||||
u8 pn[6];
|
||||
size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
|
||||
u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
|
||||
u8 *b0 = key->rx_b0;
|
||||
u8 *b = key->rx_b;
|
||||
u8 *a = key->rx_a;
|
||||
int i, blocks, last, len;
|
||||
|
||||
if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
|
||||
key->dot11RSNAStatsCCMPFormatErrors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
pos = skb->data + hdr_len;
|
||||
keyidx = pos[3];
|
||||
if (!(keyidx & (1 << 5))) {
|
||||
if (net_ratelimit()) {
|
||||
pr_debug("received packet without ExtIV flag from %pM\n",
|
||||
hdr->addr2);
|
||||
}
|
||||
key->dot11RSNAStatsCCMPFormatErrors++;
|
||||
return -2;
|
||||
}
|
||||
keyidx >>= 6;
|
||||
if (key->key_idx != keyidx) {
|
||||
pr_debug("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()) {
|
||||
pr_debug("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()) {
|
||||
pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n",
|
||||
hdr->addr2, key->rx_pn, pn);
|
||||
}
|
||||
key->dot11RSNAStatsCCMPReplays++;
|
||||
return -4;
|
||||
}
|
||||
|
||||
ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
|
||||
xor_block(mic, b, CCMP_MIC_LEN);
|
||||
|
||||
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
|
||||
last = data_len % AES_BLOCK_LEN;
|
||||
|
||||
for (i = 1; i <= blocks; i++) {
|
||||
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
|
||||
/* Decrypt, with counter */
|
||||
b0[14] = (i >> 8) & 0xff;
|
||||
b0[15] = i & 0xff;
|
||||
ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
|
||||
xor_block(pos, b, len);
|
||||
/* Authentication */
|
||||
xor_block(a, pos, len);
|
||||
ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
|
||||
pos += len;
|
||||
}
|
||||
|
||||
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
|
||||
if (net_ratelimit())
|
||||
pr_debug("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_tfm *tfm = data->tfm;
|
||||
|
||||
keyidx = data->key_idx;
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->key_idx = keyidx;
|
||||
data->tfm = tfm;
|
||||
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];
|
||||
}
|
||||
crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN);
|
||||
} 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 -1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ieee80211_ccmp_null(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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 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);
|
||||
}
|
|
@ -1,740 +0,0 @@
|
|||
/*
|
||||
* Host AP crypt: host-based TKIP encryption implementation for Host AP driver
|
||||
*
|
||||
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See README and COPYING for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.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 <asm/string.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.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 crypto_blkcipher *rx_tfm_arc4;
|
||||
struct crypto_hash *rx_tfm_michael;
|
||||
struct crypto_blkcipher *tx_tfm_arc4;
|
||||
struct crypto_hash *tx_tfm_michael;
|
||||
struct crypto_tfm *tfm_arc4;
|
||||
struct crypto_tfm *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;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||
if (priv == NULL)
|
||||
goto fail;
|
||||
priv->key_idx = key_idx;
|
||||
|
||||
priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(priv->tx_tfm_arc4)) {
|
||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
||||
"crypto API arc4\n");
|
||||
priv->tx_tfm_arc4 = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
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_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(priv->rx_tfm_arc4)) {
|
||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
||||
"crypto API arc4\n");
|
||||
priv->rx_tfm_arc4 = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
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) {
|
||||
if (priv->tx_tfm_michael)
|
||||
crypto_free_hash(priv->tx_tfm_michael);
|
||||
if (priv->tx_tfm_arc4)
|
||||
crypto_free_blkcipher(priv->tx_tfm_arc4);
|
||||
if (priv->rx_tfm_michael)
|
||||
crypto_free_hash(priv->rx_tfm_michael);
|
||||
if (priv->rx_tfm_arc4)
|
||||
crypto_free_blkcipher(priv->rx_tfm_arc4);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211_tkip_deinit(void *priv)
|
||||
{
|
||||
struct ieee80211_tkip_data *_priv = priv;
|
||||
|
||||
if (_priv) {
|
||||
if (_priv->tx_tfm_michael)
|
||||
crypto_free_hash(_priv->tx_tfm_michael);
|
||||
if (_priv->tx_tfm_arc4)
|
||||
crypto_free_blkcipher(_priv->tx_tfm_arc4);
|
||||
if (_priv->rx_tfm_michael)
|
||||
crypto_free_hash(_priv->rx_tfm_michael);
|
||||
if (_priv->rx_tfm_arc4)
|
||||
crypto_free_blkcipher(_priv->rx_tfm_arc4);
|
||||
}
|
||||
kfree(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 inline u16 Mk16_le(u16 *v)
|
||||
{
|
||||
return le16_to_cpu(*v);
|
||||
}
|
||||
|
||||
|
||||
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] ^ Mk16_le((u16 *) &TK[0]));
|
||||
PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
|
||||
PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
|
||||
PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
|
||||
PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
|
||||
PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
|
||||
|
||||
PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
|
||||
PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &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] ^ Mk16_le((u16 *) &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;
|
||||
struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
|
||||
int len;
|
||||
u8 *pos;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u8 rc4key[16], *icv;
|
||||
u32 crc;
|
||||
struct scatterlist sg;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
|
||||
skb->len < hdr_len)
|
||||
return -1;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
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);
|
||||
|
||||
len = skb->len - hdr_len;
|
||||
pos = skb_push(skb, 8);
|
||||
memmove(pos, pos + 8, hdr_len);
|
||||
pos += hdr_len;
|
||||
|
||||
*pos++ = rc4key[0];
|
||||
*pos++ = rc4key[1];
|
||||
*pos++ = rc4key[2];
|
||||
*pos++ = (tkey->key_idx << 6) | (1 << 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;
|
||||
|
||||
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;
|
||||
crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
|
||||
sg_init_one(&sg, pos, len + 4);
|
||||
ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
|
||||
|
||||
tkey->tx_iv16++;
|
||||
if (tkey->tx_iv16 == 0) {
|
||||
tkey->tx_phase1_done = 0;
|
||||
tkey->tx_iv32++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
{
|
||||
struct ieee80211_tkip_data *tkey = priv;
|
||||
struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
|
||||
u8 keyidx, *pos;
|
||||
u32 iv32;
|
||||
u16 iv16;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u8 icv[4];
|
||||
u32 crc;
|
||||
struct scatterlist sg;
|
||||
u8 rc4key[16];
|
||||
int plen;
|
||||
|
||||
if (skb->len < hdr_len + 8 + 4)
|
||||
return -1;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
pos = skb->data + hdr_len;
|
||||
keyidx = pos[3];
|
||||
if (!(keyidx & (1 << 5))) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
|
||||
" flag from %pM\n", hdr->addr2);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
keyidx >>= 6;
|
||||
if (tkey->key_idx != keyidx) {
|
||||
printk(KERN_DEBUG "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()) {
|
||||
printk(KERN_DEBUG "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 (iv32 < tkey->rx_iv32 ||
|
||||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "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;
|
||||
crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
|
||||
sg_init_one(&sg, pos, plen + 4);
|
||||
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG ": TKIP: failed to decrypt "
|
||||
"received packet from %pM\n",
|
||||
hdr->addr2);
|
||||
}
|
||||
return -7;
|
||||
}
|
||||
|
||||
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()) {
|
||||
printk(KERN_DEBUG "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_hash *tfm_michael, u8 *key, u8 *hdr,
|
||||
u8 *data, size_t data_len, u8 *mic)
|
||||
{
|
||||
struct hash_desc desc;
|
||||
struct scatterlist sg[2];
|
||||
|
||||
if (tfm_michael == NULL) {
|
||||
printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sg_init_table(sg, 2);
|
||||
sg_set_buf(&sg[0], hdr, 16);
|
||||
sg_set_buf(&sg[1], data, data_len);
|
||||
|
||||
if (crypto_hash_setkey(tfm_michael, key, 8))
|
||||
return -1;
|
||||
|
||||
desc.tfm = tfm_michael;
|
||||
desc.flags = 0;
|
||||
return crypto_hash_digest(&desc, sg, data_len + 16, mic);
|
||||
}
|
||||
|
||||
static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
|
||||
{
|
||||
struct ieee80211_hdr_4addr *hdr11;
|
||||
|
||||
hdr11 = (struct ieee80211_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;
|
||||
case 0:
|
||||
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 ieee80211_hdr_4addr *hdr;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
|
||||
printk(KERN_DEBUG "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);
|
||||
|
||||
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 ieee80211_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 ieee80211_hdr_4addr *hdr;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
if (!tkey->key_set)
|
||||
return -1;
|
||||
|
||||
michael_mic_hdr(skb, tkey->rx_hdr);
|
||||
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 ieee80211_hdr_4addr *hdr;
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
|
||||
"MSDU from %pM keyidx=%d\n",
|
||||
skb->dev ? skb->dev->name : "N/A", 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_hash *tfm = tkey->tx_tfm_michael;
|
||||
struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
|
||||
struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
|
||||
struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
|
||||
|
||||
keyidx = tkey->key_idx;
|
||||
memset(tkey, 0, sizeof(*tkey));
|
||||
tkey->key_idx = keyidx;
|
||||
|
||||
tkey->tx_tfm_michael = tfm;
|
||||
tkey->tx_tfm_arc4 = tfm2;
|
||||
tkey->rx_tfm_michael = tfm3;
|
||||
tkey->rx_tfm_arc4 = tfm4;
|
||||
|
||||
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 -1;
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
|
||||
void ieee80211_tkip_null(void)
|
||||
{
|
||||
}
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Host AP crypt: host-based WEP encryption implementation for Host AP driver
|
||||
*
|
||||
* Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See README and COPYING for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.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 crypto_blkcipher *tx_tfm;
|
||||
struct crypto_blkcipher *rx_tfm;
|
||||
};
|
||||
|
||||
static void *prism2_wep_init(int keyidx)
|
||||
{
|
||||
struct prism2_wep_data *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||
if (priv == NULL)
|
||||
goto fail;
|
||||
priv->key_idx = keyidx;
|
||||
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(priv->tx_tfm)) {
|
||||
pr_debug("could not allocate crypto API arc4\n");
|
||||
priv->tx_tfm = NULL;
|
||||
goto fail;
|
||||
}
|
||||
priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(priv->rx_tfm)) {
|
||||
pr_debug("could not allocate crypto API arc4\n");
|
||||
priv->rx_tfm = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* start WEP IV from a random value */
|
||||
get_random_bytes(&priv->iv, 4);
|
||||
|
||||
return priv;
|
||||
|
||||
fail:
|
||||
if (priv) {
|
||||
if (priv->tx_tfm)
|
||||
crypto_free_blkcipher(priv->tx_tfm);
|
||||
if (priv->rx_tfm)
|
||||
crypto_free_blkcipher(priv->rx_tfm);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void prism2_wep_deinit(void *priv)
|
||||
{
|
||||
struct prism2_wep_data *_priv = priv;
|
||||
|
||||
if (_priv) {
|
||||
if (_priv->tx_tfm)
|
||||
crypto_free_blkcipher(_priv->tx_tfm);
|
||||
if (_priv->rx_tfm)
|
||||
crypto_free_blkcipher(_priv->rx_tfm);
|
||||
}
|
||||
|
||||
kfree(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;
|
||||
struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
|
||||
u32 klen, len;
|
||||
u8 key[WEP_KEY_LEN + 3];
|
||||
u8 *pos;
|
||||
u32 crc;
|
||||
u8 *icv;
|
||||
struct scatterlist sg;
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
|
||||
sg_init_one(&sg, pos, len + 4);
|
||||
|
||||
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
|
||||
u32 klen, plen;
|
||||
u8 key[WEP_KEY_LEN + 3];
|
||||
u8 keyidx, *pos;
|
||||
u32 crc;
|
||||
u8 icv[4];
|
||||
struct scatterlist sg;
|
||||
|
||||
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;
|
||||
|
||||
crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
|
||||
sg_init_one(&sg, pos, plen + 4);
|
||||
|
||||
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
|
||||
return -7;
|
||||
|
||||
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 -1;
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
void ieee80211_wep_null(void)
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -1,203 +0,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>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in the
|
||||
file called LICENSE.
|
||||
|
||||
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/config.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 <net/net_namespace.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)
|
||||
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);
|
||||
init_timer(&ieee->crypt_deinit_timer);
|
||||
ieee->crypt_deinit_timer.data = (unsigned long)ieee;
|
||||
ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
|
||||
|
||||
spin_lock_init(&ieee->lock);
|
||||
spin_lock_init(&ieee->wpax_suitlist_lock);
|
||||
|
||||
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;
|
||||
|
||||
ieee80211_softmac_init(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;
|
||||
}
|
||||
//These function were added to load crypte module autoly
|
||||
ieee80211_tkip_null();
|
||||
ieee80211_wep_null();
|
||||
ieee80211_ccmp_null();
|
||||
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;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
|
||||
list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
|
||||
kfree(list_entry(p, struct ieee_ibss_seq, list));
|
||||
list_del(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free_netdev(dev);
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,567 +0,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 ;-)
|
||||
*
|
||||
* released under the GPL
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
|
||||
/* FIXME: add A freqs */
|
||||
|
||||
const long ieee80211_wlan_frequencies[] = {
|
||||
2412, 2417, 2422, 2427,
|
||||
2432, 2437, 2442, 2447,
|
||||
2452, 2457, 2462, 2467,
|
||||
2472, 2484
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
// printk("in %s\n",__func__);
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
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:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
fwrq->m = ieee->current_network.channel;
|
||||
fwrq->e = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
|
||||
else
|
||||
memcpy(wrqu->ap_addr.sa_data,
|
||||
ieee->current_network.bssid, ETH_ALEN);
|
||||
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
//printk("=======Set WAP:");
|
||||
ieee->sync_scan_hurryup = 1;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
/* 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);
|
||||
//printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]);
|
||||
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
if (ifup)
|
||||
ieee80211_start_protocol(ieee);
|
||||
|
||||
out:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//added by lizhaoming for auto mode
|
||||
if (target_rate == -1)
|
||||
ieee->rate = 110;
|
||||
else
|
||||
ieee->rate = target_rate/100000;
|
||||
|
||||
//FIXME: we might want to limit rate also in management protocols.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu,
|
||||
char *extra)
|
||||
{
|
||||
|
||||
wrqu->bitrate.value = ieee->rate * 100000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
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:
|
||||
up(&ieee->wx_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
chan = ieee->current_network.channel;
|
||||
|
||||
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);
|
||||
|
||||
ieee80211_start_scan_syncro(ieee);
|
||||
|
||||
ieee->set_chan(ieee->dev, chan);
|
||||
|
||||
ieee->state = IEEE80211_LINKED;
|
||||
ieee->link_change(ieee->dev);
|
||||
|
||||
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);
|
||||
|
||||
//YJ,add,080828, In prevent of lossing ping packet during scanning
|
||||
//ieee80211_sta_ps_send_null_frame(ieee, false);
|
||||
//YJ,add,080828,end
|
||||
|
||||
up(&ieee->wx_sem);
|
||||
|
||||
}
|
||||
|
||||
int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *a, union iwreq_data *wrqu,
|
||||
char *b)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
//YJ,add,080828
|
||||
//In prevent of lossing ping packet during scanning
|
||||
//ieee80211_sta_ps_send_null_frame(ieee, true);
|
||||
//YJ,add,080828,end
|
||||
|
||||
if (ieee->state == IEEE80211_LINKED) {
|
||||
queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
|
||||
/* intentionally forget to up sem */
|
||||
return 0;
|
||||
}
|
||||
|
||||
out:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
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 consistent infos. not needed otherwise
|
||||
*/
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
if (wrqu->essid.flags && wrqu->essid.length) {
|
||||
//YJ,modified,080819
|
||||
len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE;
|
||||
memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819
|
||||
strncpy(ieee->current_network.ssid, extra, len);
|
||||
ieee->current_network.ssid_len = len;
|
||||
ieee->ssid_set = 1;
|
||||
//YJ,modified,080819,end
|
||||
|
||||
//YJ,add,080819,for hidden ap
|
||||
if (len == 0) {
|
||||
memset(ieee->current_network.bssid, 0, ETH_ALEN);
|
||||
ieee->current_network.capability = 0;
|
||||
}
|
||||
//YJ,add,080819,for hidden ap,end
|
||||
} else {
|
||||
ieee->ssid_set = 0;
|
||||
ieee->current_network.ssid[0] = '\0';
|
||||
ieee->current_network.ssid_len = 0;
|
||||
}
|
||||
//printk("==========set essid %s!\n",ieee->current_network.ssid);
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
if (proto_started)
|
||||
ieee80211_start_protocol(ieee);
|
||||
out:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
up(&ieee->wx_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_wx_get_name(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu,
|
||||
char *extra)
|
||||
{
|
||||
strlcpy(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->state == IEEE80211_LINKED) ||
|
||||
(ieee->state == IEEE80211_LINKED_SCANNING))
|
||||
strlcat(wrqu->name, " link", IFNAMSIZ);
|
||||
else if (ieee->state != IEEE80211_NOLINK)
|
||||
strlcat(wrqu->name, " .....", IFNAMSIZ);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
if ((!ieee->sta_wake_up) ||
|
||||
(!ieee->ps_request_tx_ack) ||
|
||||
(!ieee->enter_sleep_state) ||
|
||||
(!ieee->ps_is_queue_empty)) {
|
||||
|
||||
printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
if (wrqu->power.disabled) {
|
||||
ieee->ps = IEEE80211_PS_DISABLED;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
switch (wrqu->power.flags & IW_POWER_MODE) {
|
||||
case IW_POWER_UNICAST_R:
|
||||
ieee->ps = IEEE80211_PS_UNICAST;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (wrqu->power.flags & IW_POWER_TIMEOUT) {
|
||||
|
||||
ieee->ps_timeout = wrqu->power.value / 1000;
|
||||
printk("Timeout %d\n", ieee->ps_timeout);
|
||||
}
|
||||
|
||||
if (wrqu->power.flags & IW_POWER_PERIOD) {
|
||||
|
||||
ret = -EOPNOTSUPP;
|
||||
goto exit;
|
||||
//wrq->value / 1024;
|
||||
|
||||
}
|
||||
exit:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
down(&ieee->wx_sem);
|
||||
|
||||
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->current_network.dtim_period *
|
||||
// ieee->current_network.beacon_interval * 1024;
|
||||
// }
|
||||
|
||||
|
||||
if (ieee->ps & IEEE80211_PS_MBCAST)
|
||||
wrqu->power.flags |= IW_POWER_ALL_R;
|
||||
else
|
||||
wrqu->power.flags |= IW_POWER_UNICAST_R;
|
||||
|
||||
exit:
|
||||
up(&ieee->wx_sem);
|
||||
return ret;
|
||||
|
||||
}
|
|
@ -1,591 +0,0 @@
|
|||
/******************************************************************************
|
||||
|
||||
Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in the
|
||||
file called LICENSE.
|
||||
|
||||
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 <asm/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];
|
||||
|
||||
*(u16 *)(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;
|
||||
|
||||
/*
|
||||
* added to care about null crypt condition, to solve that system hangs
|
||||
* when shared keys error
|
||||
*/
|
||||
if (!crypt || !crypt->ops)
|
||||
return -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211_CRYPT_TKIP
|
||||
struct ieee80211_hdr_4addr *header;
|
||||
|
||||
if (ieee->tkip_countermeasures &&
|
||||
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
|
||||
header = (struct ieee80211_hdr_4addr *)frag->data;
|
||||
if (net_ratelimit()) {
|
||||
netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
|
||||
"TX packet to %pM\n", header->addr1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* 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;
|
||||
for (i = 0; i < txb->nr_frags; i++)
|
||||
if (txb->fragments[i])
|
||||
dev_kfree_skb_any(txb->fragments[i]);
|
||||
kfree(txb);
|
||||
}
|
||||
|
||||
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 = txb_size;
|
||||
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
txb->fragments[i] = dev_alloc_skb(txb_size);
|
||||
if (unlikely(!txb->fragments[i])) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 ether_header *eh = (struct ether_header *)skb->data;
|
||||
unsigned int wme_UP = 0;
|
||||
|
||||
if (!network->QoS_Enable) {
|
||||
skb->priority = 0;
|
||||
return(wme_UP);
|
||||
}
|
||||
|
||||
if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
|
||||
const struct iphdr *ih = (struct iphdr *)(skb->data +
|
||||
sizeof(struct ether_header));
|
||||
wme_UP = (ih->tos >> 5)&0x07;
|
||||
} else if (vlan_tx_tag_present(skb)) {/* vtag packet */
|
||||
#ifndef VLAN_PRI_SHIFT
|
||||
#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */
|
||||
#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */
|
||||
#endif
|
||||
u32 tag = vlan_tx_tag_get(skb);
|
||||
wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
|
||||
} else if (ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) {
|
||||
wme_UP = 7;
|
||||
}
|
||||
|
||||
skb->priority = wme_UP;
|
||||
return(wme_UP);
|
||||
}
|
||||
|
||||
/* SKBs are added to the ieee->tx_queue. */
|
||||
int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_device *ieee = netdev_priv(dev);
|
||||
struct ieee80211_txb *txb = NULL;
|
||||
struct ieee80211_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, encrypt;
|
||||
int bytes, fc, qos_ctl, hdr_len;
|
||||
struct sk_buff *skb_frag;
|
||||
struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
|
||||
.duration_id = 0,
|
||||
.seq_ctl = 0,
|
||||
.qos_ctl = 0
|
||||
};
|
||||
u8 dest[ETH_ALEN], src[ETH_ALEN];
|
||||
|
||||
struct ieee80211_crypt_data* crypt;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
/*
|
||||
* If there is no driver handler to take the TXB, don't 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;
|
||||
}
|
||||
|
||||
ieee80211_classify(skb,&ieee->current_network);
|
||||
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;
|
||||
}
|
||||
|
||||
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 (ieee->current_network.QoS_Enable) {
|
||||
if (encrypt)
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
|
||||
IEEE80211_FCTL_WEP;
|
||||
else
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
|
||||
|
||||
} else {
|
||||
if (encrypt)
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
|
||||
IEEE80211_FCTL_WEP;
|
||||
else
|
||||
fc = IEEE80211_FTYPE_DATA | 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 {
|
||||
/* default:392 */
|
||||
frag_size = ieee->fts;
|
||||
qos_ctl = 0;
|
||||
}
|
||||
|
||||
if (ieee->current_network.QoS_Enable) {
|
||||
hdr_len = IEEE80211_3ADDR_LEN + 2;
|
||||
/* skb->priority is set in the ieee80211_classify() */
|
||||
qos_ctl |= skb->priority;
|
||||
header.qos_ctl = cpu_to_le16(qos_ctl);
|
||||
} 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, GFP_ATOMIC);
|
||||
if (unlikely(!txb)) {
|
||||
netdev_warn(ieee->dev, "Could not allocate TXB\n");
|
||||
goto failed;
|
||||
}
|
||||
txb->encrypted = encrypt;
|
||||
txb->payload_size = bytes;
|
||||
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
skb_frag = txb->fragments[i];
|
||||
skb_frag->priority = UP2AC(skb->priority);
|
||||
if (encrypt)
|
||||
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
|
||||
|
||||
frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(
|
||||
skb_frag, hdr_len);
|
||||
memcpy(frag_hdr, &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) {
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
memcpy(skb_put(skb_frag, bytes), 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);
|
||||
}
|
||||
/* Advance sequence number in data frame. */
|
||||
if (ieee->current_network.QoS_Enable) {
|
||||
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 ieee80211_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 = skb->len;
|
||||
memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len);
|
||||
}
|
||||
|
||||
success:
|
||||
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 += 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 NETDEV_TX_BUSY;
|
||||
|
||||
}
|
|
@ -1,713 +0,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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* 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 <linux/etherdevice.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
static const char *ieee80211_modes[] = {
|
||||
"?", "a", "b", "ab", "g", "ag", "bg", "abg"
|
||||
};
|
||||
|
||||
#define MAX_CUSTOM_LEN 64
|
||||
static inline char *rtl818x_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 *p;
|
||||
struct iw_event iwe;
|
||||
int i, j;
|
||||
u8 max_rate, rate;
|
||||
|
||||
/* First entry *MUST* be the AP MAC address */
|
||||
iwe.cmd = SIOCGIWAP;
|
||||
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
|
||||
start = iwe_stream_add_event(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->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_t(u8, network->ssid_len, 32);
|
||||
start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
|
||||
}
|
||||
/* Add the protocol name */
|
||||
iwe.cmd = SIOCGIWNAME;
|
||||
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
|
||||
start = iwe_stream_add_event(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(info, start, stop, &iwe, IW_EV_UINT_LEN);
|
||||
}
|
||||
|
||||
/* Add frequency/channel */
|
||||
iwe.cmd = SIOCGIWFREQ;
|
||||
iwe.u.freq.m = network->channel;
|
||||
iwe.u.freq.e = 0;
|
||||
iwe.u.freq.i = 0;
|
||||
start = iwe_stream_add_event(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 += snprintf(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 += snprintf(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 += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
|
||||
"%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
|
||||
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(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... */
|
||||
if (network->stats.signal == 0 || network->stats.rssi == 0)
|
||||
netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n",
|
||||
network->stats.signal, network->stats.rssi);
|
||||
iwe.cmd = IWEVQUAL;
|
||||
iwe.u.qual.qual = network->stats.signalstrength;
|
||||
iwe.u.qual.level = network->stats.signal;
|
||||
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(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);
|
||||
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
if (network->wpa_ie_len) {
|
||||
char buf[MAX_WPA_IE_LEN];
|
||||
memcpy(buf, network->wpa_ie, network->wpa_ie_len);
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = network->wpa_ie_len;
|
||||
start = iwe_stream_add_point(info, start, stop, &iwe, buf);
|
||||
}
|
||||
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
if (network->rsn_ie_len) {
|
||||
char buf[MAX_WPA_IE_LEN];
|
||||
memcpy(buf, network->rsn_ie, network->rsn_ie_len);
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = network->rsn_ie_len;
|
||||
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 += snprintf(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;
|
||||
int err = 0;
|
||||
char *ev = extra;
|
||||
char *stop = ev + wrqu->data.length;
|
||||
int i = 0;
|
||||
|
||||
IEEE80211_DEBUG_WX("Getting scan\n");
|
||||
down(&ieee->wx_sem);
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
if (!ieee->bHwRadioOff) {
|
||||
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 = rtl818x_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);
|
||||
up(&ieee->wx_sem);
|
||||
wrqu->data.length = ev - extra;
|
||||
wrqu->data.flags = 0;
|
||||
IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
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] != NULL) {
|
||||
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 != NULL && (*crypt)->ops != NULL &&
|
||||
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 == NULL) {
|
||||
struct ieee80211_crypt_data *new_crypt;
|
||||
|
||||
/* take WEP into use */
|
||||
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
|
||||
GFP_KERNEL);
|
||||
if (new_crypt == NULL)
|
||||
return -ENOMEM;
|
||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
||||
if (!new_crypt->ops)
|
||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
||||
|
||||
if (new_crypt->ops)
|
||||
new_crypt->priv = new_crypt->ops->init(key);
|
||||
|
||||
if (!new_crypt->ops || !new_crypt->priv) {
|
||||
kfree(new_crypt);
|
||||
new_crypt = NULL;
|
||||
|
||||
netdev_warn(ieee->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 |= (1 << 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 */
|
||||
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 |= (1 << 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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 == NULL || crypt->ops == NULL) {
|
||||
erq->length = 0;
|
||||
erq->flags |= IW_ENCODE_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(crypt->ops->name, "WEP") != 0) {
|
||||
/* only WEP is supported with wireless extensions, so just
|
||||
* report that encryption is used.
|
||||
*/
|
||||
erq->length = 0;
|
||||
erq->flags |= IW_ENCODE_ENABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
|
||||
erq->length = (len >= 0 ? len : 0);
|
||||
|
||||
erq->flags |= IW_ENCODE_ENABLED;
|
||||
|
||||
if (ieee->open_wep)
|
||||
erq->flags |= IW_ENCODE_OPEN;
|
||||
else
|
||||
erq->flags |= IW_ENCODE_RESTRICTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
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, ret = 0;
|
||||
int group_key = 0;
|
||||
const char *alg;
|
||||
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;
|
||||
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] != NULL)
|
||||
break;
|
||||
|
||||
if (i == WEP_KEYS) {
|
||||
sec.enabled = 0;
|
||||
sec.level = SEC_LEVEL_0;
|
||||
sec.flags |= SEC_LEVEL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec.enabled = 1;
|
||||
|
||||
switch (ext->alg) {
|
||||
case IW_ENCODE_ALG_WEP:
|
||||
alg = "WEP";
|
||||
break;
|
||||
case IW_ENCODE_ALG_TKIP:
|
||||
alg = "TKIP";
|
||||
break;
|
||||
case IW_ENCODE_ALG_CCMP:
|
||||
alg = "CCMP";
|
||||
break;
|
||||
default:
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ops = ieee80211_get_crypto_ops(alg);
|
||||
if (ops == NULL)
|
||||
ops = ieee80211_get_crypto_ops(alg);
|
||||
if (ops == NULL) {
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
netdev_err(ieee->dev, "========>unknown crypto alg %d\n",
|
||||
ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*crypt == NULL || (*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 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
new_crypt->ops = ops;
|
||||
if (new_crypt->ops)
|
||||
new_crypt->priv = new_crypt->ops->init(idx);
|
||||
if (new_crypt->priv == NULL) {
|
||||
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);
|
||||
netdev_err(ieee->dev, "key setting failed\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
#if 1
|
||||
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 |= (1 << idx);
|
||||
if (ext->alg == IW_ENCODE_ALG_WEP) {
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_1;
|
||||
} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_2;
|
||||
} else if (ext->alg == IW_ENCODE_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;
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
#if 1
|
||||
switch (mlme->cmd) {
|
||||
case IW_MLME_DEAUTH:
|
||||
case IW_MLME_DISASSOC:
|
||||
ieee80211_disassociate(ieee);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
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:
|
||||
ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
|
||||
break;
|
||||
|
||||
#if 1
|
||||
case IW_AUTH_WPA_ENABLED:
|
||||
ieee->wpa_enabled = (data->value) ? 1 : 0;
|
||||
break;
|
||||
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
#if 1
|
||||
int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
|
||||
{
|
||||
u8 *buf = NULL;
|
||||
|
||||
if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
|
||||
netdev_err(ieee->dev, "return error out, len:%zu\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
if (len != ie[1]+2) {
|
||||
netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
buf = kmemdup(ie, len, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
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;
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,640 +0,0 @@
|
|||
/*
|
||||
* This is part of rtl8180 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 thanks the Authors of those projects and the Ndiswrapper project
|
||||
* Authors.
|
||||
*/
|
||||
|
||||
#ifndef R8180H
|
||||
#define R8180H
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#define RTL8180_MODULE_NAME "r8180"
|
||||
#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
|
||||
#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
|
||||
#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rtnetlink.h> /* for rtnl_lock() */
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
|
||||
#include <linux/if_arp.h>
|
||||
#include "ieee80211/ieee80211.h"
|
||||
#include <asm/io.h>
|
||||
|
||||
#define EPROM_93c46 0
|
||||
#define EPROM_93c56 1
|
||||
|
||||
#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
|
||||
|
||||
#define DEFAULT_FRAG_THRESHOLD 2342U
|
||||
#define MIN_FRAG_THRESHOLD 256U
|
||||
#define DEFAULT_RTS_THRESHOLD 2342U
|
||||
#define MIN_RTS_THRESHOLD 0U
|
||||
#define MAX_RTS_THRESHOLD 2342U
|
||||
#define DEFAULT_BEACONINTERVAL 0x64U
|
||||
|
||||
#define DEFAULT_RETRY_RTS 7
|
||||
#define DEFAULT_RETRY_DATA 7
|
||||
|
||||
#define BEACON_QUEUE 6
|
||||
|
||||
#define aSifsTime 10
|
||||
|
||||
#define sCrcLng 4
|
||||
#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
|
||||
/* +by amy 080312. */
|
||||
#define RATE_ADAPTIVE_TIMER_PERIOD 300
|
||||
|
||||
enum wireless_mode {
|
||||
WIRELESS_MODE_UNKNOWN = 0x00,
|
||||
WIRELESS_MODE_A = 0x01,
|
||||
WIRELESS_MODE_B = 0x02,
|
||||
WIRELESS_MODE_G = 0x04,
|
||||
WIRELESS_MODE_AUTO = 0x08,
|
||||
};
|
||||
|
||||
struct chnl_access_setting {
|
||||
u16 sifs_timer;
|
||||
u16 difs_timer;
|
||||
u16 slot_time_timer;
|
||||
u16 eifs_timer;
|
||||
u16 cwmin_index;
|
||||
u16 cwmax_index;
|
||||
};
|
||||
|
||||
enum nic_t {
|
||||
NIC_8185 = 1,
|
||||
NIC_8185B
|
||||
};
|
||||
|
||||
typedef u32 AC_CODING;
|
||||
#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */
|
||||
#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */
|
||||
#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */
|
||||
#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */
|
||||
#define AC_MAX 4 /* Max: define total number; Should not to be used as a real
|
||||
* enum.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECWmin/ECWmax field.
|
||||
* Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
|
||||
*/
|
||||
typedef union _ECW {
|
||||
u8 charData;
|
||||
struct {
|
||||
u8 ECWmin:4;
|
||||
u8 ECWmax:4;
|
||||
} f; /* Field */
|
||||
} ECW, *PECW;
|
||||
|
||||
/*
|
||||
* ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
|
||||
*/
|
||||
typedef union _ACI_AIFSN {
|
||||
u8 charData;
|
||||
|
||||
struct {
|
||||
u8 AIFSN:4;
|
||||
u8 ACM:1;
|
||||
u8 ACI:2;
|
||||
u8 Reserved:1;
|
||||
} f; /* Field */
|
||||
} ACI_AIFSN, *PACI_AIFSN;
|
||||
|
||||
/*
|
||||
* AC Parameters Record Format.
|
||||
* Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
|
||||
*/
|
||||
typedef union _AC_PARAM {
|
||||
u32 longData;
|
||||
u8 charData[4];
|
||||
|
||||
struct {
|
||||
ACI_AIFSN AciAifsn;
|
||||
ECW Ecw;
|
||||
u16 TXOPLimit;
|
||||
} f; /* Field */
|
||||
} AC_PARAM, *PAC_PARAM;
|
||||
|
||||
struct buffer {
|
||||
struct buffer *next;
|
||||
u32 *buf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
/* YJ,modified,080828. */
|
||||
struct stats {
|
||||
unsigned long txrdu;
|
||||
unsigned long rxrdu;
|
||||
unsigned long rxnolast;
|
||||
unsigned long rxnodata;
|
||||
unsigned long rxnopointer;
|
||||
unsigned long txnperr;
|
||||
unsigned long txresumed;
|
||||
unsigned long rxerr;
|
||||
unsigned long rxoverflow;
|
||||
unsigned long rxint;
|
||||
unsigned long txbkpokint;
|
||||
unsigned long txbepoking;
|
||||
unsigned long txbkperr;
|
||||
unsigned long txbeperr;
|
||||
unsigned long txnpokint;
|
||||
unsigned long txhpokint;
|
||||
unsigned long txhperr;
|
||||
unsigned long ints;
|
||||
unsigned long shints;
|
||||
unsigned long txoverflow;
|
||||
unsigned long rxdmafail;
|
||||
unsigned long txbeacon;
|
||||
unsigned long txbeaconerr;
|
||||
unsigned long txlpokint;
|
||||
unsigned long txlperr;
|
||||
unsigned long txretry; /* retry number tony 20060601 */
|
||||
unsigned long rxcrcerrmin; /* crc error (0-500) */
|
||||
unsigned long rxcrcerrmid; /* crc error (500-1000) */
|
||||
unsigned long rxcrcerrmax; /* crc error (>1000) */
|
||||
unsigned long rxicverr; /* ICV error */
|
||||
};
|
||||
|
||||
#define MAX_LD_SLOT_NUM 10
|
||||
#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
|
||||
#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
|
||||
#define DEFAULT_KEEP_ALIVE_LEVEL 1
|
||||
#define DEFAULT_SLOT_NUM 2
|
||||
#define POWER_PROFILE_AC 0
|
||||
#define POWER_PROFILE_BATTERY 1
|
||||
|
||||
struct link_detect_t {
|
||||
u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
|
||||
* CheckForHang_period to determine
|
||||
* link status.
|
||||
*/
|
||||
u16 slot_num; /* number of CheckForHang period to determine link status,
|
||||
* default is 2.
|
||||
*/
|
||||
u16 slot_index;
|
||||
u32 num_tx_ok_in_period; /* number of packet transmitted during
|
||||
* CheckForHang.
|
||||
*/
|
||||
u32 num_rx_ok_in_period; /* number of packet received during
|
||||
* CheckForHang.
|
||||
*/
|
||||
u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
|
||||
u32 last_num_tx_unicast;
|
||||
u32 last_num_rx_unicast;
|
||||
|
||||
bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
|
||||
};
|
||||
|
||||
/* YJ,modified,080828,end */
|
||||
|
||||
/* by amy for led
|
||||
* ==========================================================================
|
||||
* LED customization.
|
||||
* ==========================================================================
|
||||
*/
|
||||
enum led_strategy_8185 {
|
||||
SW_LED_MODE0,
|
||||
SW_LED_MODE1,
|
||||
HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
|
||||
* control modes). */
|
||||
};
|
||||
|
||||
enum rt_rf_power_state {
|
||||
RF_ON,
|
||||
RF_SLEEP,
|
||||
RF_OFF
|
||||
};
|
||||
|
||||
enum _ReasonCode {
|
||||
unspec_reason = 0x1,
|
||||
auth_not_valid = 0x2,
|
||||
deauth_lv_ss = 0x3,
|
||||
inactivity = 0x4,
|
||||
ap_overload = 0x5,
|
||||
class2_err = 0x6,
|
||||
class3_err = 0x7,
|
||||
disas_lv_ss = 0x8,
|
||||
asoc_not_auth = 0x9,
|
||||
|
||||
/* ----MIC_CHECK */
|
||||
mic_failure = 0xe,
|
||||
/* ----END MIC_CHECK */
|
||||
|
||||
/* Reason code defined in 802.11i D10.0 p.28. */
|
||||
invalid_IE = 0x0d,
|
||||
four_way_tmout = 0x0f,
|
||||
two_way_tmout = 0x10,
|
||||
IE_dismatch = 0x11,
|
||||
invalid_Gcipher = 0x12,
|
||||
invalid_Pcipher = 0x13,
|
||||
invalid_AKMP = 0x14,
|
||||
unsup_RSNIEver = 0x15,
|
||||
invalid_RSNIE = 0x16,
|
||||
auth_802_1x_fail = 0x17,
|
||||
ciper_reject = 0x18,
|
||||
|
||||
/* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
|
||||
* 2005-11-15.
|
||||
*/
|
||||
QoS_unspec = 0x20, /* 32 */
|
||||
QAP_bandwidth = 0x21, /* 33 */
|
||||
poor_condition = 0x22, /* 34 */
|
||||
no_facility = 0x23, /* 35 */
|
||||
/* Where is 36??? */
|
||||
req_declined = 0x25, /* 37 */
|
||||
invalid_param = 0x26, /* 38 */
|
||||
req_not_honored = 0x27, /* 39 */
|
||||
TS_not_created = 0x2F, /* 47 */
|
||||
DL_not_allowed = 0x30, /* 48 */
|
||||
dest_not_exist = 0x31, /* 49 */
|
||||
dest_not_QSTA = 0x32, /* 50 */
|
||||
};
|
||||
|
||||
enum rt_ps_mode {
|
||||
ACTIVE, /* Active/Continuous access. */
|
||||
MAX_PS, /* Max power save mode. */
|
||||
FAST_PS /* Fast power save mode. */
|
||||
};
|
||||
|
||||
/* by amy for power save. */
|
||||
struct r8180_priv {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
short epromtype;
|
||||
int irq;
|
||||
struct ieee80211_device *ieee80211;
|
||||
|
||||
short plcp_preamble_mode; /* 0:auto 1:short 2:long */
|
||||
|
||||
spinlock_t irq_th_lock;
|
||||
spinlock_t tx_lock;
|
||||
spinlock_t ps_lock;
|
||||
spinlock_t rf_ps_lock;
|
||||
|
||||
u16 irq_mask;
|
||||
short irq_enabled;
|
||||
struct net_device *dev;
|
||||
short chan;
|
||||
short sens;
|
||||
short max_sens;
|
||||
u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
|
||||
u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
|
||||
u8 channel_plan; /* it's the channel plan index. */
|
||||
short up;
|
||||
short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
|
||||
|
||||
struct timer_list scan_timer;
|
||||
spinlock_t scan_lock;
|
||||
u8 active_probe;
|
||||
struct semaphore wx_sem;
|
||||
short hw_wep;
|
||||
|
||||
short digphy;
|
||||
short antb;
|
||||
short diversity;
|
||||
u32 key0[4];
|
||||
short (*rf_set_sens)(struct net_device *dev, short sens);
|
||||
void (*rf_set_chan)(struct net_device *dev, short ch);
|
||||
void (*rf_close)(struct net_device *dev);
|
||||
void (*rf_init)(struct net_device *dev);
|
||||
void (*rf_sleep)(struct net_device *dev);
|
||||
void (*rf_wakeup)(struct net_device *dev);
|
||||
/* short rate; */
|
||||
short promisc;
|
||||
/* stats */
|
||||
struct stats stats;
|
||||
struct link_detect_t link_detect; /* YJ,add,080828 */
|
||||
struct iw_statistics wstats;
|
||||
|
||||
/* RX stuff. */
|
||||
u32 *rxring;
|
||||
u32 *rxringtail;
|
||||
dma_addr_t rxringdma;
|
||||
struct buffer *rxbuffer;
|
||||
struct buffer *rxbufferhead;
|
||||
int rxringcount;
|
||||
u16 rxbuffersize;
|
||||
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
short rx_skb_complete;
|
||||
|
||||
u32 rx_prevlen;
|
||||
|
||||
u32 *txmapring;
|
||||
u32 *txbkpring;
|
||||
u32 *txbepring;
|
||||
u32 *txvipring;
|
||||
u32 *txvopring;
|
||||
u32 *txhpring;
|
||||
dma_addr_t txmapringdma;
|
||||
dma_addr_t txbkpringdma;
|
||||
dma_addr_t txbepringdma;
|
||||
dma_addr_t txvipringdma;
|
||||
dma_addr_t txvopringdma;
|
||||
dma_addr_t txhpringdma;
|
||||
u32 *txmapringtail;
|
||||
u32 *txbkpringtail;
|
||||
u32 *txbepringtail;
|
||||
u32 *txvipringtail;
|
||||
u32 *txvopringtail;
|
||||
u32 *txhpringtail;
|
||||
u32 *txmapringhead;
|
||||
u32 *txbkpringhead;
|
||||
u32 *txbepringhead;
|
||||
u32 *txvipringhead;
|
||||
u32 *txvopringhead;
|
||||
u32 *txhpringhead;
|
||||
struct buffer *txmapbufs;
|
||||
struct buffer *txbkpbufs;
|
||||
struct buffer *txbepbufs;
|
||||
struct buffer *txvipbufs;
|
||||
struct buffer *txvopbufs;
|
||||
struct buffer *txhpbufs;
|
||||
struct buffer *txmapbufstail;
|
||||
struct buffer *txbkpbufstail;
|
||||
struct buffer *txbepbufstail;
|
||||
struct buffer *txvipbufstail;
|
||||
struct buffer *txvopbufstail;
|
||||
struct buffer *txhpbufstail;
|
||||
|
||||
int txringcount;
|
||||
int txbuffsize;
|
||||
struct tasklet_struct irq_rx_tasklet;
|
||||
u8 dma_poll_mask;
|
||||
|
||||
/* adhoc/master mode stuff. */
|
||||
u32 *txbeaconringtail;
|
||||
dma_addr_t txbeaconringdma;
|
||||
u32 *txbeaconring;
|
||||
int txbeaconcount;
|
||||
struct buffer *txbeaconbufs;
|
||||
struct buffer *txbeaconbufstail;
|
||||
|
||||
u8 retry_data;
|
||||
u8 retry_rts;
|
||||
u16 rts;
|
||||
|
||||
/* by amy for led. */
|
||||
enum led_strategy_8185 led_strategy;
|
||||
/* by amy for led. */
|
||||
|
||||
/* by amy for power save. */
|
||||
struct timer_list watch_dog_timer;
|
||||
bool bInactivePs;
|
||||
bool bSwRfProcessing;
|
||||
enum rt_rf_power_state eInactivePowerState;
|
||||
enum rt_rf_power_state eRFPowerState;
|
||||
u32 RfOffReason;
|
||||
bool RFChangeInProgress;
|
||||
bool SetRFPowerStateInProgress;
|
||||
u8 RFProgType;
|
||||
bool bLeisurePs;
|
||||
enum rt_ps_mode dot11PowerSaveMode;
|
||||
u8 TxPollingTimes;
|
||||
|
||||
bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
|
||||
* keep eAwake until receive data or timeout.
|
||||
*/
|
||||
u8 WaitBufDataBcnCount;
|
||||
u8 WaitBufDataTimeOut;
|
||||
|
||||
/* by amy for power save. */
|
||||
/* by amy for antenna. */
|
||||
u8 EEPROMSwAntennaDiversity;
|
||||
bool EEPROMDefaultAntenna1;
|
||||
u8 RegSwAntennaDiversityMechanism;
|
||||
bool bSwAntennaDiverity;
|
||||
u8 RegDefaultAntenna;
|
||||
bool bDefaultAntenna1;
|
||||
u8 SignalStrength;
|
||||
long Stats_SignalStrength;
|
||||
long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
|
||||
* e.g. Moving Average.
|
||||
*/
|
||||
u8 SignalQuality; /* in 0-100 index. */
|
||||
long Stats_SignalQuality;
|
||||
long RecvSignalPower; /* in dBm. */
|
||||
long Stats_RecvSignalPower;
|
||||
u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
|
||||
* packet. 0: Aux, 1:Main. Added by Roger,
|
||||
* 2008.01.25.
|
||||
*/
|
||||
u32 AdRxOkCnt;
|
||||
long AdRxSignalStrength;
|
||||
u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
|
||||
u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
|
||||
u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
|
||||
* signal strength for SW Antenna Diversity.
|
||||
*/
|
||||
u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
|
||||
u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
|
||||
long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
|
||||
long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
|
||||
bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
|
||||
* strength for last time switching antenna.
|
||||
*/
|
||||
long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
|
||||
* antenna.
|
||||
*/
|
||||
struct timer_list SwAntennaDiversityTimer;
|
||||
/* by amy for antenna {by amy 080312 */
|
||||
|
||||
/* Crystal calibration. Added by Roger, 2007.12.11. */
|
||||
|
||||
bool bXtalCalibration; /* Crystal calibration.*/
|
||||
u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
|
||||
u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
|
||||
|
||||
/* Tx power tracking with thermal meter indication.
|
||||
* Added by Roger, 2007.12.11.
|
||||
*/
|
||||
|
||||
bool bTxPowerTrack; /* Tx Power tracking. */
|
||||
u8 ThermalMeter; /* Thermal meter reference indication. */
|
||||
|
||||
/* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
|
||||
* 2007-02-14.
|
||||
*/
|
||||
bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
|
||||
bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
|
||||
* by rcnjko.
|
||||
*/
|
||||
u32 FalseAlarmRegValue;
|
||||
u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
|
||||
* used in DIG.
|
||||
*/
|
||||
u8 DIG_NumberFallbackVote;
|
||||
u8 DIG_NumberUpgradeVote;
|
||||
/* For HW antenna diversity, added by Roger, 2008.01.30. */
|
||||
u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
|
||||
u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
|
||||
bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
|
||||
* evaluation.
|
||||
*/
|
||||
/* RF High Power upper/lower threshold. */
|
||||
u8 RegHiPwrUpperTh;
|
||||
u8 RegHiPwrLowerTh;
|
||||
/* RF RSSI High Power upper/lower Threshold. */
|
||||
u8 RegRSSIHiPwrUpperTh;
|
||||
u8 RegRSSIHiPwrLowerTh;
|
||||
/* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
|
||||
* by Bruce, 2007-04-12.
|
||||
*/
|
||||
u8 CurCCKRSSI;
|
||||
bool bCurCCKPkt;
|
||||
/* High Power Mechanism. Added by amy, 080312. */
|
||||
bool bToUpdateTxPwr;
|
||||
long UndecoratedSmoothedSS;
|
||||
long UndecoratedSmoothedRxPower;
|
||||
u8 RSSI;
|
||||
char RxPower;
|
||||
u8 InitialGain;
|
||||
/* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
|
||||
u32 DozePeriodInPast2Sec;
|
||||
/* Don't access BB/RF under disable PLL situation. */
|
||||
u8 InitialGainBackUp;
|
||||
u8 RegBModeGainStage;
|
||||
/* by amy for rate adaptive */
|
||||
struct timer_list rateadapter_timer;
|
||||
u32 RateAdaptivePeriod;
|
||||
bool bEnhanceTxPwr;
|
||||
bool bUpdateARFR;
|
||||
int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
|
||||
*/
|
||||
u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
|
||||
u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
|
||||
unsigned long NumTxOkTotal;
|
||||
u16 LastRetryCnt;
|
||||
u16 LastRetryRate;
|
||||
unsigned long LastTxokCnt;
|
||||
unsigned long LastRxokCnt;
|
||||
u16 CurrRetryCnt;
|
||||
unsigned long LastTxOKBytes;
|
||||
unsigned long NumTxOkBytesTotal;
|
||||
u8 LastFailTxRate;
|
||||
long LastFailTxRateSS;
|
||||
u8 FailTxRateCount;
|
||||
u32 LastTxThroughput;
|
||||
/* for up rate. */
|
||||
unsigned short bTryuping;
|
||||
u8 CurrTxRate; /* the rate before up. */
|
||||
u16 CurrRetryRate;
|
||||
u16 TryupingCount;
|
||||
u8 TryDownCountLowData;
|
||||
u8 TryupingCountNoData;
|
||||
|
||||
u8 CurrentOperaRate;
|
||||
struct work_struct reset_wq;
|
||||
struct work_struct watch_dog_wq;
|
||||
short ack_tx_to_ieee;
|
||||
|
||||
u8 dma_poll_stop_mask;
|
||||
|
||||
u16 ShortRetryLimit;
|
||||
u16 LongRetryLimit;
|
||||
u16 EarlyRxThreshold;
|
||||
u32 TransmitConfig;
|
||||
u32 ReceiveConfig;
|
||||
u32 IntrMask;
|
||||
|
||||
struct chnl_access_setting ChannelAccessSetting;
|
||||
};
|
||||
|
||||
#define MANAGE_PRIORITY 0
|
||||
#define BK_PRIORITY 1
|
||||
#define BE_PRIORITY 2
|
||||
#define VI_PRIORITY 3
|
||||
#define VO_PRIORITY 4
|
||||
#define HI_PRIORITY 5
|
||||
#define BEACON_PRIORITY 6
|
||||
|
||||
#define LOW_PRIORITY VI_PRIORITY
|
||||
#define NORM_PRIORITY VO_PRIORITY
|
||||
/* AC2Queue mapping. */
|
||||
#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
|
||||
((_ac) == WME_AC_VI) ? VI_PRIORITY : \
|
||||
((_ac) == WME_AC_BK) ? BK_PRIORITY : \
|
||||
BE_PRIORITY)
|
||||
|
||||
short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority,
|
||||
bool morefrag, short fragdesc, int rate);
|
||||
|
||||
u8 read_nic_byte(struct net_device *dev, int x);
|
||||
u32 read_nic_dword(struct net_device *dev, int x);
|
||||
u16 read_nic_word(struct net_device *dev, int x);
|
||||
void write_nic_byte(struct net_device *dev, int x, u8 y);
|
||||
void write_nic_word(struct net_device *dev, int x, u16 y);
|
||||
void write_nic_dword(struct net_device *dev, int x, u32 y);
|
||||
void force_pci_posting(struct net_device *dev);
|
||||
|
||||
void rtl8180_rtx_disable(struct net_device *);
|
||||
void rtl8180_set_anaparam(struct net_device *dev, u32 a);
|
||||
void rtl8185_set_anaparam2(struct net_device *dev, u32 a);
|
||||
void rtl8180_set_hw_wep(struct net_device *dev);
|
||||
void rtl8180_no_hw_wep(struct net_device *dev);
|
||||
void rtl8180_update_msr(struct net_device *dev);
|
||||
void rtl8180_beacon_tx_disable(struct net_device *dev);
|
||||
void rtl8180_beacon_rx_disable(struct net_device *dev);
|
||||
int rtl8180_down(struct net_device *dev);
|
||||
int rtl8180_up(struct net_device *dev);
|
||||
void rtl8180_commit(struct net_device *dev);
|
||||
void rtl8180_set_chan(struct net_device *dev, short ch);
|
||||
void write_phy(struct net_device *dev, u8 adr, u8 data);
|
||||
void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
|
||||
void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
|
||||
void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
|
||||
void rtl8185_rf_pins_enable(struct net_device *dev);
|
||||
void IPSEnter(struct net_device *dev);
|
||||
void IPSLeave(struct net_device *dev);
|
||||
int get_curr_tx_free_desc(struct net_device *dev, int priority);
|
||||
void UpdateInitialGain(struct net_device *dev);
|
||||
bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
|
||||
bool bAntDiversity);
|
||||
|
||||
void rtl8185b_adapter_start(struct net_device *dev);
|
||||
void rtl8185b_rx_enable(struct net_device *dev);
|
||||
void rtl8185b_tx_enable(struct net_device *dev);
|
||||
void rtl8180_reset(struct net_device *dev);
|
||||
void rtl8185b_irq_enable(struct net_device *dev);
|
||||
void fix_rx_fifo(struct net_device *dev);
|
||||
void fix_tx_fifo(struct net_device *dev);
|
||||
void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
|
||||
void rtl8180_rate_adapter(struct work_struct *work);
|
||||
bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
|
||||
u32 ChangeSource);
|
||||
|
||||
#endif
|
||||
|
||||
/* fun with the built-in ieee80211 stack... */
|
||||
extern int ieee80211_crypto_init(void);
|
||||
extern void ieee80211_crypto_deinit(void);
|
||||
extern int ieee80211_crypto_tkip_init(void);
|
||||
extern void ieee80211_crypto_tkip_exit(void);
|
||||
extern int ieee80211_crypto_ccmp_init(void);
|
||||
extern void ieee80211_crypto_ccmp_exit(void);
|
||||
extern int ieee80211_crypto_wep_init(void);
|
||||
extern void ieee80211_crypto_wep_exit(void);
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
This is part of rtl8180 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 tanks 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 "r8180.h"
|
||||
#include "r8180_hw.h"
|
||||
|
||||
#define EPROM_DELAY 10
|
||||
|
||||
#define EPROM_ANAPARAM_ADDRLWORD 0xd
|
||||
#define EPROM_ANAPARAM_ADDRHWORD 0xe
|
||||
|
||||
#define RFCHIPID 0x6
|
||||
#define RFCHIPID_INTERSIL 1
|
||||
#define RFCHIPID_RFMD 2
|
||||
#define RFCHIPID_PHILIPS 3
|
||||
#define RFCHIPID_MAXIM 4
|
||||
#define RFCHIPID_GCT 5
|
||||
#define RFCHIPID_RTL8225 9
|
||||
#define RF_ZEBRA2 11
|
||||
#define EPROM_TXPW_BASE 0x05
|
||||
#define RF_ZEBRA4 12
|
||||
#define RFCHIPID_RTL8255 0xa
|
||||
#define RF_PARAM 0x19
|
||||
#define RF_PARAM_DIGPHY_SHIFT 0
|
||||
#define RF_PARAM_ANTBDEFAULT_SHIFT 1
|
||||
#define RF_PARAM_CARRIERSENSE_SHIFT 2
|
||||
#define RF_PARAM_CARRIERSENSE_MASK (3<<2)
|
||||
#define ENERGY_TRESHOLD 0x17
|
||||
#define EPROM_VERSION 0x1E
|
||||
#define MAC_ADR 0x7
|
||||
|
||||
#define CIS 0x18
|
||||
|
||||
#define EPROM_TXPW_OFDM_CH1_2 0x20
|
||||
|
||||
#define EPROM_TXPW_CH1_2 0x30
|
||||
|
||||
#define RTL818X_EEPROM_CMD_READ (1 << 0)
|
||||
#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
|
||||
#define RTL818X_EEPROM_CMD_CK (1 << 2)
|
||||
#define RTL818X_EEPROM_CMD_CS (1 << 3)
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,23 +0,0 @@
|
|||
#ifndef R8180_DM_H
|
||||
#define R8180_DM_H
|
||||
|
||||
#include "r8180.h"
|
||||
/* #include "r8180_hw.h" */
|
||||
/* #include "r8180_93cx6.h" */
|
||||
void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength);
|
||||
bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex);
|
||||
bool SwitchAntenna(struct net_device *dev);
|
||||
void SwAntennaDiversity(struct net_device *dev);
|
||||
void SwAntennaDiversityTimerCallback(struct net_device *dev);
|
||||
bool CheckDig(struct net_device *dev);
|
||||
bool CheckHighPower(struct net_device *dev);
|
||||
void rtl8180_hw_dig_wq(struct work_struct *work);
|
||||
void rtl8180_tx_pw_wq(struct work_struct *work);
|
||||
void rtl8180_rate_adapter(struct work_struct *work);
|
||||
void TxPwrTracking87SE(struct net_device *dev);
|
||||
bool CheckTxPwrTracking(struct net_device *dev);
|
||||
void rtl8180_rate_adapter(struct work_struct *work);
|
||||
void timer_rate_adaptive(unsigned long data);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,588 +0,0 @@
|
|||
/*
|
||||
This is part of rtl8180 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 tanks 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 rtl8180 MAC controller */
|
||||
#ifndef R8180_HW
|
||||
#define R8180_HW
|
||||
|
||||
|
||||
#define BIT0 0x00000001
|
||||
#define BIT1 0x00000002
|
||||
#define BIT2 0x00000004
|
||||
#define BIT3 0x00000008
|
||||
#define BIT4 0x00000010
|
||||
#define BIT5 0x00000020
|
||||
#define BIT6 0x00000040
|
||||
#define BIT7 0x00000080
|
||||
#define BIT9 0x00000200
|
||||
#define BIT11 0x00000800
|
||||
#define BIT13 0x00002000
|
||||
#define BIT15 0x00008000
|
||||
#define BIT20 0x00100000
|
||||
#define BIT21 0x00200000
|
||||
#define BIT22 0x00400000
|
||||
#define BIT23 0x00800000
|
||||
#define BIT24 0x01000000
|
||||
#define BIT25 0x02000000
|
||||
#define BIT26 0x04000000
|
||||
#define BIT27 0x08000000
|
||||
#define BIT28 0x10000000
|
||||
#define BIT29 0x20000000
|
||||
#define BIT30 0x40000000
|
||||
#define BIT31 0x80000000
|
||||
|
||||
#define MAX_SLEEP_TIME (10000)
|
||||
#define MIN_SLEEP_TIME (50)
|
||||
|
||||
#define BB_HOST_BANG_EN (1<<2)
|
||||
#define BB_HOST_BANG_CLK (1<<1)
|
||||
|
||||
#define MAC0 0
|
||||
#define MAC4 4
|
||||
|
||||
#define CMD 0x37
|
||||
#define CMD_RST_SHIFT 4
|
||||
#define CMD_RX_ENABLE_SHIFT 3
|
||||
#define CMD_TX_ENABLE_SHIFT 2
|
||||
|
||||
#define EPROM_CMD 0x50
|
||||
#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4))
|
||||
#define EPROM_CMD_OPERATING_MODE_SHIFT 6
|
||||
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
|
||||
#define EPROM_CMD_CONFIG 0x3
|
||||
#define EPROM_CMD_NORMAL 0
|
||||
#define EPROM_CMD_LOAD 1
|
||||
#define EPROM_CMD_PROGRAM 2
|
||||
#define EPROM_CS_SHIFT 3
|
||||
#define EPROM_CK_SHIFT 2
|
||||
#define EPROM_W_SHIFT 1
|
||||
#define EPROM_R_SHIFT 0
|
||||
#define CONFIG2_DMA_POLLING_MODE_SHIFT 3
|
||||
|
||||
#define INTA_TXOVERFLOW (1<<15)
|
||||
#define INTA_TIMEOUT (1<<14)
|
||||
#define INTA_HIPRIORITYDESCERR (1<<9)
|
||||
#define INTA_HIPRIORITYDESCOK (1<<8)
|
||||
#define INTA_NORMPRIORITYDESCERR (1<<7)
|
||||
#define INTA_NORMPRIORITYDESCOK (1<<6)
|
||||
#define INTA_RXOVERFLOW (1<<5)
|
||||
#define INTA_RXDESCERR (1<<4)
|
||||
#define INTA_LOWPRIORITYDESCERR (1<<3)
|
||||
#define INTA_LOWPRIORITYDESCOK (1<<2)
|
||||
#define INTA_RXOK (1)
|
||||
#define INTA_MASK 0x3c
|
||||
|
||||
#define RXRING_ADDR 0xe4 /* page 0 */
|
||||
#define PGSELECT 0x5e
|
||||
#define PGSELECT_PG_SHIFT 0
|
||||
#define RX_CONF 0x44
|
||||
#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
|
||||
(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
|
||||
#define RX_CHECK_BSSID_SHIFT 23
|
||||
#define ACCEPT_PWR_FRAME_SHIFT 22
|
||||
#define ACCEPT_MNG_FRAME_SHIFT 20
|
||||
#define ACCEPT_CTL_FRAME_SHIFT 19
|
||||
#define ACCEPT_DATA_FRAME_SHIFT 18
|
||||
#define ACCEPT_ICVERR_FRAME_SHIFT 12
|
||||
#define ACCEPT_CRCERR_FRAME_SHIFT 5
|
||||
#define ACCEPT_BCAST_FRAME_SHIFT 3
|
||||
#define ACCEPT_MCAST_FRAME_SHIFT 2
|
||||
#define ACCEPT_ALLMAC_FRAME_SHIFT 0
|
||||
#define ACCEPT_NICMAC_FRAME_SHIFT 1
|
||||
|
||||
#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
|
||||
#define RX_FIFO_THRESHOLD_SHIFT 13
|
||||
#define RX_FIFO_THRESHOLD_NONE 7
|
||||
#define RX_AUTORESETPHY_SHIFT 28
|
||||
|
||||
#define TX_CONF 0x40
|
||||
#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
|
||||
#define TX_LOOPBACK_SHIFT 17
|
||||
#define TX_LOOPBACK_NONE 0
|
||||
#define TX_LOOPBACK_CONTINUE 3
|
||||
#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
|
||||
#define TX_DPRETRY_SHIFT 0
|
||||
#define R8180_MAX_RETRY 255
|
||||
#define TX_RTSRETRY_SHIFT 8
|
||||
#define TX_NOICV_SHIFT 19
|
||||
#define TX_NOCRC_SHIFT 16
|
||||
#define TX_DMA_POLLING 0xd9
|
||||
#define TX_DMA_POLLING_BEACON_SHIFT 7
|
||||
#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
|
||||
#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
|
||||
#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
|
||||
#define TX_MANAGEPRIORITY_RING_ADDR 0x0C
|
||||
#define TX_BKPRIORITY_RING_ADDR 0x10
|
||||
#define TX_BEPRIORITY_RING_ADDR 0x14
|
||||
#define TX_VIPRIORITY_RING_ADDR 0x20
|
||||
#define TX_VOPRIORITY_RING_ADDR 0x24
|
||||
#define TX_HIGHPRIORITY_RING_ADDR 0x28
|
||||
#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
|
||||
#define MAX_RX_DMA_2048 7
|
||||
#define MAX_RX_DMA_1024 6
|
||||
#define MAX_RX_DMA_SHIFT 10
|
||||
#define INT_TIMEOUT 0x48
|
||||
#define CONFIG3_CLKRUN_SHIFT 2
|
||||
#define CONFIG3_ANAPARAM_W_SHIFT 6
|
||||
#define ANAPARAM 0x54
|
||||
#define BEACON_INTERVAL 0x70
|
||||
#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
|
||||
(1<<6)|(1<<7)|(1<<8)|(1<<9))
|
||||
#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \
|
||||
(1<<8)|(1<<9))
|
||||
#define ATIM 0x72
|
||||
#define EPROM_CS_SHIFT 3
|
||||
#define EPROM_CK_SHIFT 2
|
||||
#define PHY_ADR 0x7c
|
||||
#define SECURITY 0x5f /* 1209 this is sth wrong */
|
||||
#define SECURITY_WEP_TX_ENABLE_SHIFT 1
|
||||
#define SECURITY_WEP_RX_ENABLE_SHIFT 0
|
||||
#define SECURITY_ENCRYP_104 1
|
||||
#define SECURITY_ENCRYP_SHIFT 4
|
||||
#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
|
||||
#define KEY0 0x90 /* 1209 this is sth wrong */
|
||||
#define CONFIG2_ANTENNA_SHIFT 6
|
||||
#define TX_BEACON_RING_ADDR 0x4c
|
||||
#define CONFIG0_WEP40_SHIFT 7
|
||||
#define CONFIG0_WEP104_SHIFT 6
|
||||
#define AGCRESET_SHIFT 5
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Operational registers offsets in PCI (I/O) space.
|
||||
* RealTek names are used.
|
||||
*/
|
||||
|
||||
#define TSFTR 0x0018
|
||||
|
||||
#define TLPDA 0x0020
|
||||
|
||||
#define BSSID 0x002E
|
||||
|
||||
#define CR 0x0037
|
||||
|
||||
#define RF_SW_CONFIG 0x8 /* store data which is transmitted to RF for driver */
|
||||
#define RF_SW_CFG_SI BIT1
|
||||
#define EIFS 0x2D /* Extended InterFrame Space Timer, in unit of 4 us. */
|
||||
|
||||
#define BRSR 0x34 /* Basic rate set */
|
||||
|
||||
#define IMR 0x006C
|
||||
#define ISR 0x003C
|
||||
|
||||
#define TCR 0x0040
|
||||
|
||||
#define RCR 0x0044
|
||||
|
||||
#define TimerInt 0x0048
|
||||
|
||||
#define CR9346 0x0050
|
||||
|
||||
#define CONFIG0 0x0051
|
||||
#define CONFIG2 0x0053
|
||||
|
||||
#define MSR 0x0058
|
||||
|
||||
#define CONFIG3 0x0059
|
||||
#define CONFIG4 0x005A
|
||||
/* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6 */
|
||||
/* Mac0x60 = 0x000004C6 power save parameters */
|
||||
#define ANAPARM_ASIC_ON 0xB0054D00
|
||||
#define ANAPARM2_ASIC_ON 0x000004C6
|
||||
|
||||
#define ANAPARM_ON ANAPARM_ASIC_ON
|
||||
#define ANAPARM2_ON ANAPARM2_ASIC_ON
|
||||
|
||||
#define TESTR 0x005B
|
||||
|
||||
#define PSR 0x005E
|
||||
|
||||
#define BcnItv 0x0070
|
||||
|
||||
#define AtimWnd 0x0072
|
||||
|
||||
#define BintrItv 0x0074
|
||||
|
||||
#define PhyAddr 0x007C
|
||||
#define PhyDataR 0x007E
|
||||
|
||||
/* following are for rtl8185 */
|
||||
#define RFPinsOutput 0x80
|
||||
#define RFPinsEnable 0x82
|
||||
#define RF_TIMING 0x8c
|
||||
#define RFPinsSelect 0x84
|
||||
#define ANAPARAM2 0x60
|
||||
#define RF_PARA 0x88
|
||||
#define RFPinsInput 0x86
|
||||
#define GP_ENABLE 0x90
|
||||
#define GPIO 0x91
|
||||
#define SW_CONTROL_GPIO 0x400
|
||||
#define TX_ANTENNA 0x9f
|
||||
#define TX_GAIN_OFDM 0x9e
|
||||
#define TX_GAIN_CCK 0x9d
|
||||
#define WPA_CONFIG 0xb0
|
||||
#define TX_AGC_CTL 0x9c
|
||||
#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
|
||||
#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
|
||||
#define TX_AGC_CTL_FEEDBACK_ANT 2
|
||||
#define RESP_RATE 0x34
|
||||
#define SIFS 0xb4
|
||||
#define DIFS 0xb5
|
||||
|
||||
#define SLOT 0xb6
|
||||
#define CW_CONF 0xbc
|
||||
#define CW_CONF_PERPACKET_RETRY_SHIFT 1
|
||||
#define CW_CONF_PERPACKET_CW_SHIFT 0
|
||||
#define CW_VAL 0xbd
|
||||
#define MAX_RESP_RATE_SHIFT 4
|
||||
#define MIN_RESP_RATE_SHIFT 0
|
||||
#define RATE_FALLBACK 0xbe
|
||||
|
||||
#define CONFIG5 0x00D8
|
||||
|
||||
#define PHYPR 0xDA /* 0xDA - 0x0B PHY Parameter Register. */
|
||||
|
||||
#define FEMR 0x1D4 /* Function Event Mask register */
|
||||
|
||||
#define FFER 0x00FC
|
||||
#define FFER_END 0x00FF
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Bitmasks for specific register functions.
|
||||
* Names are derived from the register name and function name.
|
||||
*
|
||||
* <REGISTER>_<FUNCTION>[<bit>]
|
||||
*
|
||||
* this leads to some awkward names...
|
||||
*/
|
||||
|
||||
#define BRSR_BPLCP ((1 << 8))
|
||||
#define BRSR_MBR ((1 << 1)|(1 << 0))
|
||||
#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0))
|
||||
#define BRSR_MBR0 ((1 << 0))
|
||||
#define BRSR_MBR1 ((1 << 1))
|
||||
|
||||
#define CR_RST ((1 << 4))
|
||||
#define CR_RE ((1 << 3))
|
||||
#define CR_TE ((1 << 2))
|
||||
#define CR_MulRW ((1 << 0))
|
||||
|
||||
#define IMR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
|
||||
#define IMR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
|
||||
#define IMR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
|
||||
#define IMR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
|
||||
#define IMR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
|
||||
#define IMR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
|
||||
#define IMR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
|
||||
#define IMR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
|
||||
#define IMR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
|
||||
#define IMR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
|
||||
#define IMR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
|
||||
#define IMR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
|
||||
#define IMR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
|
||||
#define IMR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
|
||||
#define IMR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
|
||||
#define IMR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
|
||||
#define IMR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
|
||||
#define IMR_RER ((1 << 8)) /*Rx Error Interrupt */
|
||||
#define IMR_ROK ((1 << 7)) /*Receive OK Interrupt */
|
||||
#define IMR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
|
||||
#define IMR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
|
||||
#define IMR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
|
||||
#define IMR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
|
||||
#define IMR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
|
||||
#define IMR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
|
||||
#define IMR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
|
||||
#define IMR_TMGDOK ((1 << 30))
|
||||
#define ISR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
|
||||
#define ISR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
|
||||
#define ISR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
|
||||
#define ISR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
|
||||
#define ISR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
|
||||
#define ISR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
|
||||
#define ISR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
|
||||
#define ISR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
|
||||
#define ISR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
|
||||
#define ISR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
|
||||
#define ISR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
|
||||
#define ISR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
|
||||
#define ISR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
|
||||
#define ISR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
|
||||
#define ISR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
|
||||
#define ISR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
|
||||
#define ISR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
|
||||
#define ISR_RER ((1 << 8)) /*Rx Error Interrupt */
|
||||
#define ISR_ROK ((1 << 7)) /*Receive OK Interrupt */
|
||||
#define ISR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
|
||||
#define ISR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
|
||||
#define ISR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
|
||||
#define ISR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
|
||||
#define ISR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
|
||||
#define ISR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
|
||||
#define ISR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
|
||||
|
||||
/* these definition is used for Tx/Rx test temporarily */
|
||||
#define ISR_TLPDER ISR_TVIDER
|
||||
#define ISR_TLPDOK ISR_TVIDOK
|
||||
#define ISR_TNPDER ISR_TVODER
|
||||
#define ISR_TNPDOK ISR_TVODOK
|
||||
#define ISR_TimeOut ISR_TimeOut1
|
||||
#define ISR_RXFOVW ISR_FOVW
|
||||
|
||||
|
||||
#define HW_VERID_R8180_F 3
|
||||
#define HW_VERID_R8180_ABCD 2
|
||||
#define HW_VERID_R8185_ABC 4
|
||||
#define HW_VERID_R8185_D 5
|
||||
#define HW_VERID_R8185B_B 6
|
||||
|
||||
#define TCR_CWMIN ((1 << 31))
|
||||
#define TCR_SWSEQ ((1 << 30))
|
||||
#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25))
|
||||
#define TCR_HWVERID_SHIFT 25
|
||||
#define TCR_SAT ((1 << 24))
|
||||
#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */
|
||||
#define TCR_MXDMA_MASK ((1 << 23)|(1 << 22)|(1 << 21))
|
||||
#define TCR_MXDMA_1024 6
|
||||
#define TCR_MXDMA_2048 7
|
||||
#define TCR_MXDMA_SHIFT 21
|
||||
#define TCR_DISCW ((1 << 20))
|
||||
#define TCR_ICV ((1 << 19))
|
||||
#define TCR_LBK ((1 << 18)|(1 << 17))
|
||||
#define TCR_LBK1 ((1 << 18))
|
||||
#define TCR_LBK0 ((1 << 17))
|
||||
#define TCR_CRC ((1 << 16))
|
||||
#define TCR_DPRETRY_MASK ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8))
|
||||
#define TCR_RTSRETRY_MASK ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7))
|
||||
#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */
|
||||
|
||||
#define RCR_ONLYERLPKT ((1 << 31))
|
||||
#define RCR_CS_SHIFT 29
|
||||
#define RCR_CS_MASK ((1 << 30) | (1 << 29))
|
||||
#define RCR_ENMARP ((1 << 28))
|
||||
#define RCR_CBSSID ((1 << 23))
|
||||
#define RCR_APWRMGT ((1 << 22))
|
||||
#define RCR_ADD3 ((1 << 21))
|
||||
#define RCR_AMF ((1 << 20))
|
||||
#define RCR_ACF ((1 << 19))
|
||||
#define RCR_ADF ((1 << 18))
|
||||
#define RCR_RXFTH ((1 << 15)|(1 << 14)|(1 << 13))
|
||||
#define RCR_RXFTH2 ((1 << 15))
|
||||
#define RCR_RXFTH1 ((1 << 14))
|
||||
#define RCR_RXFTH0 ((1 << 13))
|
||||
#define RCR_AICV ((1 << 12))
|
||||
#define RCR_MXDMA ((1 << 10)|(1 << 9)|(1 << 8))
|
||||
#define RCR_MXDMA2 ((1 << 10))
|
||||
#define RCR_MXDMA1 ((1 << 9))
|
||||
#define RCR_MXDMA0 ((1 << 8))
|
||||
#define RCR_9356SEL ((1 << 6))
|
||||
#define RCR_ACRC32 ((1 << 5))
|
||||
#define RCR_AB ((1 << 3))
|
||||
#define RCR_AM ((1 << 2))
|
||||
#define RCR_APM ((1 << 1))
|
||||
#define RCR_AAP ((1 << 0))
|
||||
|
||||
#define CR9346_EEM ((1 << 7)|(1 << 6))
|
||||
#define CR9346_EEM1 ((1 << 7))
|
||||
#define CR9346_EEM0 ((1 << 6))
|
||||
#define CR9346_EECS ((1 << 3))
|
||||
#define CR9346_EESK ((1 << 2))
|
||||
#define CR9346_EED1 ((1 << 1))
|
||||
#define CR9346_EED0 ((1 << 0))
|
||||
|
||||
#define CONFIG3_PARM_En ((1 << 6))
|
||||
#define CONFIG3_FuncRegEn ((1 << 1))
|
||||
|
||||
#define CONFIG4_PWRMGT ((1 << 5))
|
||||
|
||||
#define MSR_LINK_MASK ((1 << 2)|(1 << 3))
|
||||
#define MSR_LINK_MANAGED 2
|
||||
#define MSR_LINK_NONE 0
|
||||
#define MSR_LINK_SHIFT 2
|
||||
#define MSR_LINK_ADHOC 1
|
||||
#define MSR_LINK_MASTER 3
|
||||
|
||||
#define BcnItv_BcnItv (0x01FF)
|
||||
|
||||
#define AtimWnd_AtimWnd (0x01FF)
|
||||
|
||||
#define BintrItv_BintrItv (0x01FF)
|
||||
|
||||
#define FEMR_INTR ((1 << 15))
|
||||
#define FEMR_WKUP ((1 << 14))
|
||||
#define FEMR_GWAKE ((1 << 4))
|
||||
|
||||
#define FFER_INTR ((1 << 15))
|
||||
#define FFER_GWAKE ((1 << 4))
|
||||
|
||||
/* Three wire mode. */
|
||||
#define SW_THREE_WIRE 0
|
||||
#define HW_THREE_WIRE 2
|
||||
/* RTL8187S by amy */
|
||||
#define HW_THREE_WIRE_PI 5
|
||||
#define HW_THREE_WIRE_SI 6
|
||||
/* by amy */
|
||||
#define TCR_LRL_OFFSET 0
|
||||
#define TCR_SRL_OFFSET 8
|
||||
#define TCR_MXDMA_OFFSET 21
|
||||
#define TCR_DISReqQsize_OFFSET 28
|
||||
#define TCR_DurProcMode_OFFSET 30
|
||||
|
||||
#define RCR_MXDMA_OFFSET 8
|
||||
#define RCR_FIFO_OFFSET 13
|
||||
|
||||
#define AckTimeOutReg 0x79 /* ACK timeout register, in unit of 4 us. */
|
||||
|
||||
#define RFTiming 0x8C
|
||||
|
||||
#define TPPollStop 0x93
|
||||
|
||||
#define TXAGC_CTL 0x9C /*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */
|
||||
#define CCK_TXAGC 0x9D
|
||||
#define OFDM_TXAGC 0x9E
|
||||
#define ANTSEL 0x9F
|
||||
|
||||
#define ACM_CONTROL 0x00BF /* ACM Control Registe */
|
||||
|
||||
#define IntMig 0xE2 /* Interrupt Migration (0xE2 ~ 0xE3) */
|
||||
|
||||
#define TID_AC_MAP 0xE8 /* TID to AC Mapping Register */
|
||||
|
||||
#define ANAPARAM3 0xEE /* <RJ_TODO_8185B> How to use it? */
|
||||
|
||||
#define AC_VO_PARAM 0xF0 /* AC_VO Parameters Record */
|
||||
#define AC_VI_PARAM 0xF4 /* AC_VI Parameters Record */
|
||||
#define AC_BE_PARAM 0xF8 /* AC_BE Parameters Record */
|
||||
#define AC_BK_PARAM 0xFC /* AC_BK Parameters Record */
|
||||
|
||||
#define GPIOCtrl 0x16B /*GPIO Control Register. */
|
||||
#define ARFR 0x1E0 /* Auto Rate Fallback Register (0x1e0 ~ 0x1e2) */
|
||||
|
||||
#define RFSW_CTRL 0x272 /* 0x272-0x273. */
|
||||
#define SW_3W_DB0 0x274 /* Software 3-wire data buffer bit 31~0. */
|
||||
#define SW_3W_DB1 0x278 /* Software 3-wire data buffer bit 63~32. */
|
||||
#define SW_3W_CMD0 0x27C /* Software 3-wire Control/Status Register. */
|
||||
#define SW_3W_CMD1 0x27D /* Software 3-wire Control/Status Register. */
|
||||
|
||||
#define PI_DATA_READ 0X360 /* 0x360 - 0x361 Parallel Interface Data Register. */
|
||||
#define SI_DATA_READ 0x362 /* 0x362 - 0x363 Serial Interface Data Register. */
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
8185B TPPollStop bits (offset 0x93, 1 byte)
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
#define TPPOLLSTOP_BQ (0x01 << 7)
|
||||
#define TPPOLLSTOP_AC_VIQ (0x01 << 4)
|
||||
|
||||
#define MSR_LINK_ENEDCA (1<<4)
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
8187B AC_XX_PARAM bits
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte)
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
#define VOQ_ACM_EN (0x01 << 7) /*BIT7 */
|
||||
#define VIQ_ACM_EN (0x01 << 6) /*BIT6 */
|
||||
#define BEQ_ACM_EN (0x01 << 5) /*BIT5 */
|
||||
#define ACM_HW_EN (0x01 << 4) /*BIT4 */
|
||||
#define VOQ_ACM_CTL (0x01 << 2) /*BIT2 */ /* Set to 1 when AC_VO used time reaches or exceeds the admitted time */
|
||||
#define VIQ_ACM_CTL (0x01 << 1) /*BIT1 */ /* Set to 1 when AC_VI used time reaches or exceeds the admitted time */
|
||||
#define BEQ_ACM_CTL (0x01 << 0) /*BIT0 */ /* Set to 1 when AC_BE used time reaches or exceeds the admitted time */
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
8185B SW_3W_CMD bits (Offset 0x27C-0x27D, 16bit)
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
#define SW_3W_CMD0_HOLD ((1 << 7))
|
||||
#define SW_3W_CMD1_RE ((1 << 0)) /* BIT8 */
|
||||
#define SW_3W_CMD1_WE ((1 << 1)) /* BIT9 */
|
||||
#define SW_3W_CMD1_DONE ((1 << 2)) /* BIT10 */
|
||||
|
||||
#define BB_HOST_BANG_RW (1 << 3)
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
8185B RATE_FALLBACK_CTL bits (Offset 0xBE, 8bit)
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
#define RATE_FALLBACK_CTL_ENABLE ((1 << 7))
|
||||
#define RATE_FALLBACK_CTL_ENABLE_RTSCTS ((1 << 6))
|
||||
/* Auto rate fallback per 2^n retry. */
|
||||
#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00
|
||||
#define RATE_FALLBACK_CTL_AUTO_STEP1 0x01
|
||||
#define RATE_FALLBACK_CTL_AUTO_STEP2 0x02
|
||||
#define RATE_FALLBACK_CTL_AUTO_STEP3 0x03
|
||||
|
||||
|
||||
#define RTL8225z2_ANAPARAM_OFF 0x55480658
|
||||
#define RTL8225z2_ANAPARAM2_OFF 0x72003f70
|
||||
/* by amy for power save */
|
||||
#define RF_CHANGE_BY_HW BIT30
|
||||
#define RF_CHANGE_BY_PS BIT29
|
||||
#define RF_CHANGE_BY_IPS BIT28
|
||||
/* by amy for power save */
|
||||
/* by amy for antenna */
|
||||
#define EEPROM_SW_REVD_OFFSET 0x3f
|
||||
|
||||
/* BIT[8-9] is for SW Antenna Diversity.
|
||||
* Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable.
|
||||
*/
|
||||
#define EEPROM_SW_AD_MASK 0x0300
|
||||
#define EEPROM_SW_AD_ENABLE 0x0100
|
||||
|
||||
/* BIT[10-11] determine if Antenna 1 is the Default Antenna.
|
||||
* Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE.
|
||||
*/
|
||||
#define EEPROM_DEF_ANT_MASK 0x0C00
|
||||
#define EEPROM_DEF_ANT_1 0x0400
|
||||
/*by amy for antenna */
|
||||
/* {by amy 080312 */
|
||||
/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10. */
|
||||
#define EEPROM_RSV 0x7C
|
||||
#define EEPROM_XTAL_CAL_XOUT_MASK 0x0F /* 0x7C[3:0], Crystal calibration for Xout. */
|
||||
#define EEPROM_XTAL_CAL_XIN_MASK 0xF0 /* 0x7C[7:4], Crystal calibration for Xin. */
|
||||
#define EEPROM_THERMAL_METER_MASK 0x0F00 /* 0x7D[3:0], Thermal meter reference level. */
|
||||
#define EEPROM_XTAL_CAL_ENABLE 0x1000 /* 0x7D[4], Crystal calibration enabled/disabled BIT. */
|
||||
#define EEPROM_THERMAL_METER_ENABLE 0x2000 /* 0x7D[5], Thermal meter enabled/disabled BIT. */
|
||||
#define EN_LPF_CAL 0x238 /* Enable LPF Calibration. */
|
||||
#define PWR_METER_EN BIT1
|
||||
/* <RJ_TODO_8185B> where are false alarm counters in 8185B? */
|
||||
#define CCK_FALSE_ALARM 0xD0
|
||||
/* by amy 080312} */
|
||||
|
||||
/* YJ,add for Country IE, 080630 */
|
||||
#define EEPROM_COUNTRY_CODE 0x2E
|
||||
/* YJ,add,080630,end */
|
||||
|
||||
#endif
|
|
@ -1,34 +0,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 rtl8225 radio frontend.
|
||||
*
|
||||
* *Many* thanks to Realtek Corp. for their great support!
|
||||
*/
|
||||
|
||||
#include "r8180.h"
|
||||
|
||||
#define RTL8225_ANAPARAM_ON 0xa0000b59
|
||||
#define RTL8225_ANAPARAM_OFF 0xa00beb59
|
||||
#define RTL8225_ANAPARAM2_OFF 0x840dec11
|
||||
#define RTL8225_ANAPARAM2_ON 0x860dec11
|
||||
#define RTL8225_ANAPARAM_SLEEP 0xa00bab59
|
||||
#define RTL8225_ANAPARAM2_SLEEP 0x840dec11
|
||||
|
||||
void rtl8225z2_rf_init(struct net_device *dev);
|
||||
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch);
|
||||
void rtl8225z2_rf_close(struct net_device *dev);
|
||||
|
||||
void RF_WriteReg(struct net_device *dev, u8 offset, u16 data);
|
||||
u16 RF_ReadReg(struct net_device *dev, u8 offset);
|
||||
|
||||
void rtl8180_set_mode(struct net_device *dev, int mode);
|
||||
void rtl8180_set_mode(struct net_device *dev, int mode);
|
||||
bool SetZebraRFPowerState8185(struct net_device *dev,
|
||||
enum rt_rf_power_state eRFPowerState);
|
||||
void rtl8225z4_rf_sleep(struct net_device *dev);
|
||||
void rtl8225z4_rf_wakeup(struct net_device *dev);
|
||||
|
|
@ -1,811 +0,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 rtl8225
|
||||
* radio frontend.
|
||||
*
|
||||
* *Many* thanks to Realtek Corp. for their great support!
|
||||
*/
|
||||
|
||||
#include "r8180_hw.h"
|
||||
#include "r8180_rtl8225.h"
|
||||
#include "r8180_93cx6.h"
|
||||
|
||||
#include "ieee80211/dot11d.h"
|
||||
|
||||
static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
|
||||
{
|
||||
int i;
|
||||
u16 out, select;
|
||||
u8 bit;
|
||||
u32 bangdata = (data << 4) | (adr & 0xf);
|
||||
|
||||
out = read_nic_word(dev, RFPinsOutput) & 0xfff3;
|
||||
|
||||
write_nic_word(dev, RFPinsEnable,
|
||||
(read_nic_word(dev, RFPinsEnable) | 0x7));
|
||||
|
||||
select = read_nic_word(dev, RFPinsSelect);
|
||||
|
||||
write_nic_word(dev, RFPinsSelect, select | 0x7 |
|
||||
SW_CONTROL_GPIO);
|
||||
|
||||
force_pci_posting(dev);
|
||||
udelay(10);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
|
||||
|
||||
force_pci_posting(dev);
|
||||
udelay(2);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, out);
|
||||
|
||||
force_pci_posting(dev);
|
||||
udelay(10);
|
||||
|
||||
for (i = 15; i >= 0; i--) {
|
||||
bit = (bangdata & (1 << i)) >> i;
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, bit | out);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
|
||||
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
|
||||
|
||||
i--;
|
||||
bit = (bangdata & (1 << i)) >> i;
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
|
||||
write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, bit | out);
|
||||
|
||||
}
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
|
||||
|
||||
force_pci_posting(dev);
|
||||
udelay(10);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
|
||||
|
||||
write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);
|
||||
|
||||
rtl8185_rf_pins_enable(dev);
|
||||
}
|
||||
|
||||
static const u8 rtl8225_agc[] = {
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
|
||||
0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
|
||||
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
|
||||
0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
|
||||
0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
|
||||
0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
|
||||
0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
|
||||
0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
|
||||
0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
|
||||
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
|
||||
0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
|
||||
0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
};
|
||||
|
||||
static const u32 rtl8225_chan[] = {
|
||||
0,
|
||||
0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
|
||||
0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
|
||||
};
|
||||
|
||||
static const u8 rtl8225z2_gain_bg[] = {
|
||||
0x23, 0x15, 0xa5, /* -82-1dBm */
|
||||
0x23, 0x15, 0xb5, /* -82-2dBm */
|
||||
0x23, 0x15, 0xc5, /* -82-3dBm */
|
||||
0x33, 0x15, 0xc5, /* -78dBm */
|
||||
0x43, 0x15, 0xc5, /* -74dBm */
|
||||
0x53, 0x15, 0xc5, /* -70dBm */
|
||||
0x63, 0x15, 0xc5, /* -66dBm */
|
||||
};
|
||||
|
||||
static const u8 rtl8225z2_gain_a[] = {
|
||||
0x13, 0x27, 0x5a, /* -82dBm */
|
||||
0x23, 0x23, 0x58, /* -82dBm */
|
||||
0x33, 0x1f, 0x56, /* -82dBm */
|
||||
0x43, 0x1b, 0x54, /* -78dBm */
|
||||
0x53, 0x17, 0x51, /* -74dBm */
|
||||
0x63, 0x24, 0x4f, /* -70dBm */
|
||||
0x73, 0x0f, 0x4c, /* -66dBm */
|
||||
};
|
||||
|
||||
static const u16 rtl8225z2_rxgain[] = {
|
||||
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
|
||||
0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
|
||||
0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
|
||||
0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
|
||||
0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
|
||||
0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
|
||||
0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
|
||||
0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
|
||||
0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
|
||||
0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
|
||||
0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
|
||||
0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
|
||||
|
||||
};
|
||||
|
||||
static void rtl8225z2_set_gain(struct net_device *dev, short gain)
|
||||
{
|
||||
const u8 *rtl8225_gain;
|
||||
struct r8180_priv *priv = ieee80211_priv(dev);
|
||||
u8 mode = priv->ieee80211->mode;
|
||||
|
||||
if (mode == IEEE_B || mode == IEEE_G)
|
||||
rtl8225_gain = rtl8225z2_gain_bg;
|
||||
else
|
||||
rtl8225_gain = rtl8225z2_gain_a;
|
||||
|
||||
write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
|
||||
write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
|
||||
write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
|
||||
write_phy_ofdm(dev, 0x21, 0x37);
|
||||
}
|
||||
|
||||
static u32 read_rtl8225(struct net_device *dev, u8 adr)
|
||||
{
|
||||
u32 data2Write = ((u32)(adr & 0x1f)) << 27;
|
||||
u32 dataRead;
|
||||
u32 mask;
|
||||
u16 oval, oval2, oval3, tmp;
|
||||
int i;
|
||||
short bit, rw;
|
||||
u8 wLength = 6;
|
||||
u8 rLength = 12;
|
||||
u8 low2high = 0;
|
||||
|
||||
oval = read_nic_word(dev, RFPinsOutput);
|
||||
oval2 = read_nic_word(dev, RFPinsEnable);
|
||||
oval3 = read_nic_word(dev, RFPinsSelect);
|
||||
|
||||
write_nic_word(dev, RFPinsEnable, (oval2|0xf));
|
||||
write_nic_word(dev, RFPinsSelect, (oval3|0xf));
|
||||
|
||||
dataRead = 0;
|
||||
|
||||
oval &= ~0xf;
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
|
||||
udelay(4);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, oval);
|
||||
udelay(5);
|
||||
|
||||
rw = 0;
|
||||
|
||||
mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));
|
||||
|
||||
for (i = 0; i < wLength/2; i++) {
|
||||
bit = ((data2Write&mask) != 0) ? 1 : 0;
|
||||
write_nic_word(dev, RFPinsOutput, bit | oval | rw);
|
||||
udelay(1);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
bit | oval | BB_HOST_BANG_CLK | rw);
|
||||
udelay(2);
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
bit | oval | BB_HOST_BANG_CLK | rw);
|
||||
udelay(2);
|
||||
|
||||
mask = (low2high) ? (mask<<1) : (mask>>1);
|
||||
|
||||
if (i == 2) {
|
||||
rw = BB_HOST_BANG_RW;
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
bit | oval | BB_HOST_BANG_CLK | rw);
|
||||
udelay(2);
|
||||
write_nic_word(dev, RFPinsOutput, bit | oval | rw);
|
||||
udelay(2);
|
||||
break;
|
||||
}
|
||||
|
||||
bit = ((data2Write&mask) != 0) ? 1 : 0;
|
||||
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
oval | bit | rw | BB_HOST_BANG_CLK);
|
||||
udelay(2);
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
oval | bit | rw | BB_HOST_BANG_CLK);
|
||||
udelay(2);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, oval | bit | rw);
|
||||
udelay(1);
|
||||
|
||||
mask = (low2high) ? (mask<<1) : (mask>>1);
|
||||
}
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, rw|oval);
|
||||
udelay(2);
|
||||
mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));
|
||||
|
||||
/*
|
||||
* We must set data pin to HW controlled, otherwise RF can't driver it
|
||||
* and value RF register won't be able to read back properly.
|
||||
*/
|
||||
write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));
|
||||
|
||||
for (i = 0; i < rLength; i++) {
|
||||
write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
|
||||
udelay(2);
|
||||
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
|
||||
udelay(2);
|
||||
write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
|
||||
udelay(2);
|
||||
tmp = read_nic_word(dev, RFPinsInput);
|
||||
|
||||
dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);
|
||||
|
||||
write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);
|
||||
|
||||
mask = (low2high) ? (mask<<1) : (mask>>1);
|
||||
}
|
||||
|
||||
write_nic_word(dev, RFPinsOutput,
|
||||
BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
|
||||
udelay(2);
|
||||
|
||||
write_nic_word(dev, RFPinsEnable, oval2);
|
||||
write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
|
||||
write_nic_word(dev, RFPinsOutput, 0x3a0);
|
||||
|
||||
return dataRead;
|
||||
}
|
||||
|
||||
void rtl8225z2_rf_close(struct net_device *dev)
|
||||
{
|
||||
RF_WriteReg(dev, 0x4, 0x1f);
|
||||
|
||||
force_pci_posting(dev);
|
||||
mdelay(1);
|
||||
|
||||
rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
|
||||
rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map dBm into Tx power index according to current HW model, for example,
|
||||
* RF and PA, and current wireless mode.
|
||||
*/
|
||||
static s8 DbmToTxPwrIdx(struct r8180_priv *priv,
|
||||
enum wireless_mode mode, s32 PowerInDbm)
|
||||
{
|
||||
bool bUseDefault = true;
|
||||
s8 TxPwrIdx = 0;
|
||||
|
||||
/*
|
||||
* OFDM Power in dBm = Index * 0.5 + 0
|
||||
* CCK Power in dBm = Index * 0.25 + 13
|
||||
*/
|
||||
s32 tmp = 0;
|
||||
|
||||
if (mode == WIRELESS_MODE_G) {
|
||||
bUseDefault = false;
|
||||
tmp = (2 * PowerInDbm);
|
||||
|
||||
if (tmp < 0)
|
||||
TxPwrIdx = 0;
|
||||
else if (tmp > 40) /* 40 means 20 dBm. */
|
||||
TxPwrIdx = 40;
|
||||
else
|
||||
TxPwrIdx = (s8)tmp;
|
||||
} else if (mode == WIRELESS_MODE_B) {
|
||||
bUseDefault = false;
|
||||
tmp = (4 * PowerInDbm) - 52;
|
||||
|
||||
if (tmp < 0)
|
||||
TxPwrIdx = 0;
|
||||
else if (tmp > 28) /* 28 means 20 dBm. */
|
||||
TxPwrIdx = 28;
|
||||
else
|
||||
TxPwrIdx = (s8)tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* TRUE if we want to use a default implementation.
|
||||
* We shall set it to FALSE when we have exact translation formula
|
||||
* for target IC. 070622, by rcnjko.
|
||||
*/
|
||||
if (bUseDefault) {
|
||||
if (PowerInDbm < 0)
|
||||
TxPwrIdx = 0;
|
||||
else if (PowerInDbm > 35)
|
||||
TxPwrIdx = 35;
|
||||
else
|
||||
TxPwrIdx = (u8)PowerInDbm;
|
||||
}
|
||||
|
||||
return TxPwrIdx;
|
||||
}
|
||||
|
||||
void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
|
||||
{
|
||||
struct r8180_priv *priv = ieee80211_priv(dev);
|
||||
u8 max_cck_power_level;
|
||||
u8 max_ofdm_power_level;
|
||||
u8 min_ofdm_power_level;
|
||||
char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
|
||||
char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);
|
||||
|
||||
if (IS_DOT11D_ENABLE(priv->ieee80211) &&
|
||||
IS_DOT11D_STATE_DONE(priv->ieee80211)) {
|
||||
u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
|
||||
u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
|
||||
MaxTxPwrInDbm);
|
||||
u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
|
||||
MaxTxPwrInDbm);
|
||||
|
||||
if (cck_power_level > CckMaxPwrIdx)
|
||||
cck_power_level = CckMaxPwrIdx;
|
||||
if (ofdm_power_level > OfdmMaxPwrIdx)
|
||||
ofdm_power_level = OfdmMaxPwrIdx;
|
||||
}
|
||||
|
||||
max_cck_power_level = 15;
|
||||
max_ofdm_power_level = 25;
|
||||
min_ofdm_power_level = 10;
|
||||
|
||||
if (cck_power_level > 35)
|
||||
cck_power_level = 35;
|
||||
|
||||
write_nic_byte(dev, CCK_TXAGC, cck_power_level);
|
||||
force_pci_posting(dev);
|
||||
mdelay(1);
|
||||
|
||||
if (ofdm_power_level > 35)
|
||||
ofdm_power_level = 35;
|
||||
|
||||
if (priv->up == 0) {
|
||||
write_phy_ofdm(dev, 2, 0x42);
|
||||
write_phy_ofdm(dev, 5, 0x00);
|
||||
write_phy_ofdm(dev, 6, 0x40);
|
||||
write_phy_ofdm(dev, 7, 0x00);
|
||||
write_phy_ofdm(dev, 8, 0x40);
|
||||
}
|
||||
|
||||
write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
|
||||
|
||||
if (ofdm_power_level <= 11) {
|
||||
write_phy_ofdm(dev, 0x07, 0x5c);
|
||||
write_phy_ofdm(dev, 0x09, 0x5c);
|
||||
}
|
||||
|
||||
if (ofdm_power_level <= 17) {
|
||||
write_phy_ofdm(dev, 0x07, 0x54);
|
||||
write_phy_ofdm(dev, 0x09, 0x54);
|
||||
} else {
|
||||
write_phy_ofdm(dev, 0x07, 0x50);
|
||||
write_phy_ofdm(dev, 0x09, 0x50);
|
||||
}
|
||||
|
||||
force_pci_posting(dev);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch)
|
||||
{
|
||||
rtl8225z2_SetTXPowerLevel(dev, ch);
|
||||
|
||||
RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
|
||||
|
||||
if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch])
|
||||
RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
force_pci_posting(dev);
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
static void rtl8225_host_pci_init(struct net_device *dev)
|
||||
{
|
||||
write_nic_word(dev, RFPinsOutput, 0x480);
|
||||
|
||||
rtl8185_rf_pins_enable(dev);
|
||||
|
||||
write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO);
|
||||
|
||||
write_nic_byte(dev, GP_ENABLE, 0);
|
||||
|
||||
force_pci_posting(dev);
|
||||
mdelay(200);
|
||||
|
||||
/* bit 6 is for RF on/off detection */
|
||||
write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
|
||||
}
|
||||
|
||||
void rtl8225z2_rf_init(struct net_device *dev)
|
||||
{
|
||||
struct r8180_priv *priv = ieee80211_priv(dev);
|
||||
int i;
|
||||
short channel = 1;
|
||||
u16 brsr;
|
||||
u32 data;
|
||||
|
||||
priv->chan = channel;
|
||||
|
||||
rtl8225_host_pci_init(dev);
|
||||
|
||||
write_nic_dword(dev, RF_TIMING, 0x000a8008);
|
||||
|
||||
brsr = read_nic_word(dev, BRSR);
|
||||
|
||||
write_nic_word(dev, BRSR, 0xffff);
|
||||
|
||||
write_nic_dword(dev, RF_PARA, 0x100044);
|
||||
|
||||
rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
|
||||
write_nic_byte(dev, CONFIG3, 0x44);
|
||||
rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
|
||||
|
||||
rtl8185_rf_pins_enable(dev);
|
||||
|
||||
write_rtl8225(dev, 0x0, 0x2bf); mdelay(1);
|
||||
write_rtl8225(dev, 0x1, 0xee0); mdelay(1);
|
||||
write_rtl8225(dev, 0x2, 0x44d); mdelay(1);
|
||||
write_rtl8225(dev, 0x3, 0x441); mdelay(1);
|
||||
write_rtl8225(dev, 0x4, 0x8c3); mdelay(1);
|
||||
write_rtl8225(dev, 0x5, 0xc72); mdelay(1);
|
||||
write_rtl8225(dev, 0x6, 0xe6); mdelay(1);
|
||||
write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1);
|
||||
write_rtl8225(dev, 0x8, 0x3f); mdelay(1);
|
||||
write_rtl8225(dev, 0x9, 0x335); mdelay(1);
|
||||
write_rtl8225(dev, 0xa, 0x9d4); mdelay(1);
|
||||
write_rtl8225(dev, 0xb, 0x7bb); mdelay(1);
|
||||
write_rtl8225(dev, 0xc, 0x850); mdelay(1);
|
||||
write_rtl8225(dev, 0xd, 0xcdf); mdelay(1);
|
||||
write_rtl8225(dev, 0xe, 0x2b); mdelay(1);
|
||||
write_rtl8225(dev, 0xf, 0x114);
|
||||
|
||||
mdelay(100);
|
||||
|
||||
write_rtl8225(dev, 0x0, 0x1b7);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
|
||||
write_rtl8225(dev, 0x1, i + 1);
|
||||
write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
|
||||
}
|
||||
|
||||
write_rtl8225(dev, 0x3, 0x80);
|
||||
write_rtl8225(dev, 0x5, 0x4);
|
||||
|
||||
write_rtl8225(dev, 0x0, 0xb7);
|
||||
|
||||
write_rtl8225(dev, 0x2, 0xc4d);
|
||||
|
||||
/* FIXME!! rtl8187 we have to check if calibrarion
|
||||
* is successful and eventually cal. again (repeat
|
||||
* the two write on reg 2)
|
||||
*/
|
||||
data = read_rtl8225(dev, 6);
|
||||
if (!(data & 0x00000080)) {
|
||||
write_rtl8225(dev, 0x02, 0x0c4d);
|
||||
force_pci_posting(dev); mdelay(200);
|
||||
write_rtl8225(dev, 0x02, 0x044d);
|
||||
force_pci_posting(dev); mdelay(100);
|
||||
data = read_rtl8225(dev, 6);
|
||||
if (!(data & 0x00000080))
|
||||
DMESGW("RF Calibration Failed!!!!\n");
|
||||
}
|
||||
|
||||
mdelay(200);
|
||||
|
||||
write_rtl8225(dev, 0x0, 0x2bf);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
|
||||
write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
|
||||
mdelay(1);
|
||||
|
||||
/* enable writing AGC table */
|
||||
write_phy_ofdm(dev, 0xa, i + 0x80);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
force_pci_posting(dev);
|
||||
mdelay(1);
|
||||
|
||||
write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x0d, 0x43);
|
||||
write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */
|
||||
write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
|
||||
write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
|
||||
|
||||
rtl8225z2_set_gain(dev, 4);
|
||||
|
||||
write_phy_cck(dev, 0x0, 0x98); mdelay(1);
|
||||
write_phy_cck(dev, 0x3, 0x20); mdelay(1);
|
||||
write_phy_cck(dev, 0x4, 0x7e); mdelay(1);
|
||||
write_phy_cck(dev, 0x5, 0x12); mdelay(1);
|
||||
write_phy_cck(dev, 0x6, 0xfc); mdelay(1);
|
||||
write_phy_cck(dev, 0x7, 0x78); mdelay(1);
|
||||
write_phy_cck(dev, 0x8, 0x2e); mdelay(1);
|
||||
write_phy_cck(dev, 0x10, 0x93); mdelay(1);
|
||||
write_phy_cck(dev, 0x11, 0x88); mdelay(1);
|
||||
write_phy_cck(dev, 0x12, 0x47); mdelay(1);
|
||||
write_phy_cck(dev, 0x13, 0xd0);
|
||||
write_phy_cck(dev, 0x19, 0x00);
|
||||
write_phy_cck(dev, 0x1a, 0xa0);
|
||||
write_phy_cck(dev, 0x1b, 0x08);
|
||||
write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */
|
||||
write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
|
||||
write_phy_cck(dev, 0x42, 0x15); mdelay(1);
|
||||
write_phy_cck(dev, 0x43, 0x18); mdelay(1);
|
||||
write_phy_cck(dev, 0x44, 0x36); mdelay(1);
|
||||
write_phy_cck(dev, 0x45, 0x35); mdelay(1);
|
||||
write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
|
||||
write_phy_cck(dev, 0x47, 0x25); mdelay(1);
|
||||
write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
|
||||
write_phy_cck(dev, 0x49, 0x12); mdelay(1);
|
||||
write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
|
||||
write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
|
||||
write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
|
||||
|
||||
write_nic_byte(dev, 0x5b, 0x0d); mdelay(1);
|
||||
|
||||
rtl8225z2_SetTXPowerLevel(dev, channel);
|
||||
|
||||
/* RX antenna default to A */
|
||||
write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */
|
||||
write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
|
||||
|
||||
rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */
|
||||
|
||||
/* switch to high-speed 3-wire
|
||||
* last digit. 2 for both cck and ofdm
|
||||
*/
|
||||
write_nic_dword(dev, 0x94, 0x15c00002);
|
||||
rtl8185_rf_pins_enable(dev);
|
||||
|
||||
rtl8225z2_rf_set_chan(dev, priv->chan);
|
||||
}
|
||||
|
||||
#define MAX_DOZE_WAITING_TIMES_85B 20
|
||||
#define MAX_POLLING_24F_TIMES_87SE 10
|
||||
#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5
|
||||
|
||||
bool SetZebraRFPowerState8185(struct net_device *dev,
|
||||
enum rt_rf_power_state eRFPowerState)
|
||||
{
|
||||
struct r8180_priv *priv = ieee80211_priv(dev);
|
||||
u8 btCR9346, btConfig3;
|
||||
bool bActionAllowed = true, bTurnOffBB = true;
|
||||
u8 u1bTmp;
|
||||
int i;
|
||||
bool bResult = true;
|
||||
u8 QueueID;
|
||||
|
||||
if (priv->SetRFPowerStateInProgress == true)
|
||||
return false;
|
||||
|
||||
priv->SetRFPowerStateInProgress = true;
|
||||
|
||||
btCR9346 = read_nic_byte(dev, CR9346);
|
||||
write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
|
||||
|
||||
btConfig3 = read_nic_byte(dev, CONFIG3);
|
||||
write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
|
||||
|
||||
switch (eRFPowerState) {
|
||||
case RF_ON:
|
||||
write_nic_word(dev, 0x37C, 0x00EC);
|
||||
|
||||
/* turn on AFE */
|
||||
write_nic_byte(dev, 0x54, 0x00);
|
||||
write_nic_byte(dev, 0x62, 0x00);
|
||||
|
||||
/* turn on RF */
|
||||
RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
|
||||
RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
|
||||
|
||||
/* turn on RF again */
|
||||
RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
|
||||
RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
|
||||
|
||||
/* turn on BB */
|
||||
write_phy_ofdm(dev, 0x10, 0x40);
|
||||
write_phy_ofdm(dev, 0x12, 0x40);
|
||||
|
||||
/* Avoid power down at init time. */
|
||||
write_nic_byte(dev, CONFIG4, priv->RFProgType);
|
||||
|
||||
u1bTmp = read_nic_byte(dev, 0x24E);
|
||||
write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
|
||||
break;
|
||||
case RF_SLEEP:
|
||||
for (QueueID = 0, i = 0; QueueID < 6;) {
|
||||
if (get_curr_tx_free_desc(dev, QueueID) ==
|
||||
priv->txringcount) {
|
||||
QueueID++;
|
||||
continue;
|
||||
} else {
|
||||
priv->TxPollingTimes++;
|
||||
if (priv->TxPollingTimes >=
|
||||
LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
|
||||
bActionAllowed = false;
|
||||
break;
|
||||
} else
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
if (bActionAllowed) {
|
||||
/* turn off BB RXIQ matrix to cut off rx signal */
|
||||
write_phy_ofdm(dev, 0x10, 0x00);
|
||||
write_phy_ofdm(dev, 0x12, 0x00);
|
||||
|
||||
/* turn off RF */
|
||||
RF_WriteReg(dev, 0x4, 0x0000);
|
||||
RF_WriteReg(dev, 0x0, 0x0000);
|
||||
|
||||
/* turn off AFE except PLL */
|
||||
write_nic_byte(dev, 0x62, 0xff);
|
||||
write_nic_byte(dev, 0x54, 0xec);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
while (true) {
|
||||
u8 tmp24F = read_nic_byte(dev, 0x24f);
|
||||
|
||||
if ((tmp24F == 0x01) ||
|
||||
(tmp24F == 0x09)) {
|
||||
bTurnOffBB = true;
|
||||
break;
|
||||
} else {
|
||||
udelay(10);
|
||||
i++;
|
||||
priv->TxPollingTimes++;
|
||||
|
||||
if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
|
||||
bTurnOffBB = false;
|
||||
break;
|
||||
} else
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bTurnOffBB) {
|
||||
/* turn off BB */
|
||||
u1bTmp = read_nic_byte(dev, 0x24E);
|
||||
write_nic_byte(dev, 0x24E,
|
||||
(u1bTmp | BIT5 | BIT6));
|
||||
|
||||
/* turn off AFE PLL */
|
||||
write_nic_byte(dev, 0x54, 0xFC);
|
||||
write_nic_word(dev, 0x37C, 0x00FC);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RF_OFF:
|
||||
for (QueueID = 0, i = 0; QueueID < 6;) {
|
||||
if (get_curr_tx_free_desc(dev, QueueID) ==
|
||||
priv->txringcount) {
|
||||
QueueID++;
|
||||
continue;
|
||||
} else {
|
||||
udelay(10);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= MAX_DOZE_WAITING_TIMES_85B)
|
||||
break;
|
||||
}
|
||||
|
||||
/* turn off BB RXIQ matrix to cut off rx signal */
|
||||
write_phy_ofdm(dev, 0x10, 0x00);
|
||||
write_phy_ofdm(dev, 0x12, 0x00);
|
||||
|
||||
/* turn off RF */
|
||||
RF_WriteReg(dev, 0x4, 0x0000);
|
||||
RF_WriteReg(dev, 0x0, 0x0000);
|
||||
|
||||
/* turn off AFE except PLL */
|
||||
write_nic_byte(dev, 0x62, 0xff);
|
||||
write_nic_byte(dev, 0x54, 0xec);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (true) {
|
||||
u8 tmp24F = read_nic_byte(dev, 0x24f);
|
||||
|
||||
if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
|
||||
bTurnOffBB = true;
|
||||
break;
|
||||
} else {
|
||||
bTurnOffBB = false;
|
||||
udelay(10);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > MAX_POLLING_24F_TIMES_87SE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bTurnOffBB) {
|
||||
/* turn off BB */
|
||||
u1bTmp = read_nic_byte(dev, 0x24E);
|
||||
write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
|
||||
|
||||
/* turn off AFE PLL (80M) */
|
||||
write_nic_byte(dev, 0x54, 0xFC);
|
||||
write_nic_word(dev, 0x37C, 0x00FC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
btConfig3 &= ~(CONFIG3_PARM_En);
|
||||
write_nic_byte(dev, CONFIG3, btConfig3);
|
||||
|
||||
btCR9346 &= ~(0xC0);
|
||||
write_nic_byte(dev, CR9346, btCR9346);
|
||||
|
||||
if (bResult && bActionAllowed)
|
||||
priv->eRFPowerState = eRFPowerState;
|
||||
|
||||
priv->SetRFPowerStateInProgress = false;
|
||||
|
||||
return bResult && bActionAllowed;
|
||||
}
|
||||
|
||||
void rtl8225z4_rf_sleep(struct net_device *dev)
|
||||
{
|
||||
MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS);
|
||||
}
|
||||
|
||||
void rtl8225z4_rf_wakeup(struct net_device *dev)
|
||||
{
|
||||
MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
This is part of rtl8180 OpenSource driver - v 0.3
|
||||
Copyright (C) Andrea Merello 2004 <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 thanks 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
|
||||
#include <linux/wireless.h>
|
||||
#include "ieee80211/ieee80211.h"
|
||||
extern struct iw_handler_def r8180_wx_handlers_def;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -545,20 +545,18 @@ static struct recv_frame *decryptor(struct adapter *padapter,
|
|||
static struct recv_frame *portctrl(struct adapter *adapter,
|
||||
struct recv_frame *precv_frame)
|
||||
{
|
||||
u8 *psta_addr = NULL, *ptr;
|
||||
u8 *psta_addr, *ptr;
|
||||
uint auth_alg;
|
||||
struct recv_frame *pfhdr;
|
||||
struct sta_info *psta;
|
||||
struct sta_priv *pstapriv;
|
||||
struct recv_frame *prtnframe;
|
||||
u16 ether_type = 0;
|
||||
u16 ether_type;
|
||||
u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
|
||||
struct rx_pkt_attrib *pattrib;
|
||||
__be16 be_tmp;
|
||||
|
||||
|
||||
pstapriv = &adapter->stapriv;
|
||||
psta = rtw_get_stainfo(pstapriv, psta_addr);
|
||||
|
||||
auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
|
||||
|
||||
|
@ -566,24 +564,23 @@ static struct recv_frame *portctrl(struct adapter *adapter,
|
|||
pfhdr = precv_frame;
|
||||
pattrib = &pfhdr->attrib;
|
||||
psta_addr = pattrib->ta;
|
||||
psta = rtw_get_stainfo(pstapriv, psta_addr);
|
||||
|
||||
prtnframe = NULL;
|
||||
|
||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n", adapter->securitypriv.dot11AuthAlgrthm));
|
||||
|
||||
if (auth_alg == 2) {
|
||||
/* get ether_type */
|
||||
ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
|
||||
memcpy(ðer_type, ptr, 2);
|
||||
ether_type = ntohs((unsigned short)ether_type);
|
||||
|
||||
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
|
||||
/* blocked */
|
||||
/* only accept EAPOL frame */
|
||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==1\n"));
|
||||
|
||||
prtnframe = precv_frame;
|
||||
|
||||
/* get ether_type */
|
||||
ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
|
||||
memcpy(&be_tmp, ptr, 2);
|
||||
ether_type = ntohs(be_tmp);
|
||||
|
||||
if (ether_type == eapol_type) {
|
||||
prtnframe = precv_frame;
|
||||
} else {
|
||||
|
|
|
@ -359,7 +359,7 @@ static char *translate_scan(struct adapter *padapter,
|
|||
if (wpa_len > 0) {
|
||||
p = buf;
|
||||
_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
|
||||
p += sprintf(p, "wpa_ie =");
|
||||
p += sprintf(p, "wpa_ie=");
|
||||
for (i = 0; i < wpa_len; i++)
|
||||
p += sprintf(p, "%02x", wpa_ie[i]);
|
||||
|
||||
|
@ -376,7 +376,7 @@ static char *translate_scan(struct adapter *padapter,
|
|||
if (rsn_len > 0) {
|
||||
p = buf;
|
||||
_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
|
||||
p += sprintf(p, "rsn_ie =");
|
||||
p += sprintf(p, "rsn_ie=");
|
||||
for (i = 0; i < rsn_len; i++)
|
||||
p += sprintf(p, "%02x", rsn_ie[i]);
|
||||
_rtw_memset(&iwe, 0, sizeof(iwe));
|
||||
|
@ -2899,7 +2899,7 @@ static int rtw_p2p_get_status(struct net_device *dev,
|
|||
/* Commented by Albert 2010/10/12 */
|
||||
/* Because of the output size limitation, I had removed the "Role" information. */
|
||||
/* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
|
||||
sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
|
||||
sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
|
||||
wrqu->data.length = strlen(extra);
|
||||
|
||||
return ret;
|
||||
|
@ -2918,7 +2918,7 @@ static int rtw_p2p_get_req_cm(struct net_device *dev,
|
|||
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
|
||||
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
||||
|
||||
sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
|
||||
sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
|
||||
wrqu->data.length = strlen(extra);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2935,7 +2935,7 @@ static int rtw_p2p_get_role(struct net_device *dev,
|
|||
pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
|
||||
pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
|
||||
|
||||
sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
|
||||
sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
|
||||
wrqu->data.length = strlen(extra);
|
||||
return ret;
|
||||
}
|
||||
|
@ -3022,7 +3022,7 @@ static int rtw_p2p_get_op_ch(struct net_device *dev,
|
|||
|
||||
DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
|
||||
|
||||
sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
|
||||
sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
|
||||
wrqu->data.length = strlen(extra);
|
||||
return ret;
|
||||
}
|
||||
|
@ -3043,7 +3043,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
|
|||
u8 blnMatch = 0;
|
||||
u16 attr_content = 0;
|
||||
uint attr_contentlen = 0;
|
||||
/* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
|
||||
/* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
|
||||
u8 attr_content_str[6 + 17] = {0x00};
|
||||
|
||||
/* Commented by Albert 20110727 */
|
||||
|
@ -3079,7 +3079,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
|
|||
rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
|
||||
if (attr_contentlen) {
|
||||
attr_content = be16_to_cpu(be_tmp);
|
||||
sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
|
||||
sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
|
||||
blnMatch = 1;
|
||||
}
|
||||
}
|
||||
|
@ -3091,7 +3091,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
|
|||
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
|
||||
|
||||
if (!blnMatch)
|
||||
sprintf(attr_content_str, "\n\nM = 0000");
|
||||
sprintf(attr_content_str, "\n\nM=0000");
|
||||
|
||||
if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
|
||||
return -EFAULT;
|
||||
|
@ -3172,9 +3172,9 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
|
|||
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
|
||||
|
||||
if (!blnMatch)
|
||||
snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
|
||||
snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL");
|
||||
else
|
||||
snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
|
||||
snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
|
||||
attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
|
||||
|
||||
if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
|
||||
|
@ -3198,7 +3198,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
|
|||
u8 blnMatch = 0;
|
||||
u8 dev_type[8] = {0x00};
|
||||
uint dev_type_len = 0;
|
||||
u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
|
||||
u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
|
||||
|
||||
/* Commented by Albert 20121209 */
|
||||
/* The input data is the MAC address which the application wants to know its device type. */
|
||||
|
@ -3239,7 +3239,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
|
|||
|
||||
memcpy(&be_tmp, dev_type, 2);
|
||||
type = be16_to_cpu(be_tmp);
|
||||
sprintf(dev_type_str, "\n\nN =%.2d", type);
|
||||
sprintf(dev_type_str, "\n\nN=%.2d", type);
|
||||
blnMatch = 1;
|
||||
}
|
||||
}
|
||||
|
@ -3252,7 +3252,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
|
|||
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
|
||||
|
||||
if (!blnMatch)
|
||||
sprintf(dev_type_str, "\n\nN = 00");
|
||||
sprintf(dev_type_str, "\n\nN=00");
|
||||
|
||||
if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
|
||||
return -EFAULT;
|
||||
|
@ -3277,7 +3277,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
|
|||
u8 blnMatch = 0;
|
||||
u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
|
||||
uint dev_len = 0;
|
||||
u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */
|
||||
u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */
|
||||
|
||||
/* Commented by Albert 20121225 */
|
||||
/* The input data is the MAC address which the application wants to know its device name. */
|
||||
|
@ -3310,7 +3310,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
|
|||
if (wpsie) {
|
||||
rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
|
||||
if (dev_len) {
|
||||
sprintf(dev_name_str, "\n\nN =%s", dev_name);
|
||||
sprintf(dev_name_str, "\n\nN=%s", dev_name);
|
||||
blnMatch = 1;
|
||||
}
|
||||
}
|
||||
|
@ -3323,7 +3323,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
|
|||
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
|
||||
|
||||
if (!blnMatch)
|
||||
sprintf(dev_name_str, "\n\nN = 0000");
|
||||
sprintf(dev_name_str, "\n\nN=0000");
|
||||
|
||||
if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
|
||||
return -EFAULT;
|
||||
|
@ -3349,7 +3349,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
|
|||
u8 attr_content[2] = {0x00};
|
||||
|
||||
u8 inv_proc_str[17 + 8] = {0x00};
|
||||
/* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
|
||||
/* +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */
|
||||
|
||||
/* Commented by Ouden 20121226 */
|
||||
/* The application wants to know P2P initiation procedure is supported or not. */
|
||||
|
@ -3397,12 +3397,12 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
|
|||
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
|
||||
|
||||
if (!blnMatch) {
|
||||
sprintf(inv_proc_str, "\nIP =-1");
|
||||
sprintf(inv_proc_str, "\nIP=-1");
|
||||
} else {
|
||||
if (attr_content[0] & 0x20)
|
||||
sprintf(inv_proc_str, "\nIP = 1");
|
||||
sprintf(inv_proc_str, "\nIP=1");
|
||||
else
|
||||
sprintf(inv_proc_str, "\nIP = 0");
|
||||
sprintf(inv_proc_str, "\nIP=0");
|
||||
}
|
||||
if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
|
||||
return -EFAULT;
|
||||
|
@ -3512,7 +3512,7 @@ static int rtw_p2p_invite_req(struct net_device *dev,
|
|||
/* The input data contains two informations. */
|
||||
/* 1. First information is the P2P device address which you want to send to. */
|
||||
/* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
|
||||
/* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
|
||||
/* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
|
||||
/* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
|
||||
|
||||
DBG_88E("[%s] data = %s\n", __func__, extra);
|
||||
|
@ -3805,48 +3805,48 @@ static int rtw_p2p_set(struct net_device *dev,
|
|||
|
||||
#ifdef CONFIG_88EU_P2P
|
||||
DBG_88E("[%s] extra = %s\n", __func__, extra);
|
||||
if (!memcmp(extra, "enable =", 7)) {
|
||||
if (!memcmp(extra, "enable=", 7)) {
|
||||
rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
|
||||
} else if (!memcmp(extra, "setDN =", 6)) {
|
||||
} else if (!memcmp(extra, "setDN=", 6)) {
|
||||
wrqu->data.length -= 6;
|
||||
rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
|
||||
} else if (!memcmp(extra, "profilefound =", 13)) {
|
||||
} else if (!memcmp(extra, "profilefound=", 13)) {
|
||||
wrqu->data.length -= 13;
|
||||
rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
|
||||
} else if (!memcmp(extra, "prov_disc =", 10)) {
|
||||
} else if (!memcmp(extra, "prov_disc=", 10)) {
|
||||
wrqu->data.length -= 10;
|
||||
rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
|
||||
} else if (!memcmp(extra, "nego =", 5)) {
|
||||
} else if (!memcmp(extra, "nego=", 5)) {
|
||||
wrqu->data.length -= 5;
|
||||
rtw_p2p_connect(dev, info, wrqu, &extra[5]);
|
||||
} else if (!memcmp(extra, "intent =", 7)) {
|
||||
} else if (!memcmp(extra, "intent=", 7)) {
|
||||
/* Commented by Albert 2011/03/23 */
|
||||
/* The wrqu->data.length will include the null character */
|
||||
/* So, we will decrease 7 + 1 */
|
||||
wrqu->data.length -= 8;
|
||||
rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
|
||||
} else if (!memcmp(extra, "ssid =", 5)) {
|
||||
} else if (!memcmp(extra, "ssid=", 5)) {
|
||||
wrqu->data.length -= 5;
|
||||
rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
|
||||
} else if (!memcmp(extra, "got_wpsinfo =", 12)) {
|
||||
} else if (!memcmp(extra, "got_wpsinfo=", 12)) {
|
||||
wrqu->data.length -= 12;
|
||||
rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
|
||||
} else if (!memcmp(extra, "listen_ch =", 10)) {
|
||||
} else if (!memcmp(extra, "listen_ch=", 10)) {
|
||||
/* Commented by Albert 2011/05/24 */
|
||||
/* The wrqu->data.length will include the null character */
|
||||
/* So, we will decrease (10 + 1) */
|
||||
wrqu->data.length -= 11;
|
||||
rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
|
||||
} else if (!memcmp(extra, "op_ch =", 6)) {
|
||||
} else if (!memcmp(extra, "op_ch=", 6)) {
|
||||
/* Commented by Albert 2011/05/24 */
|
||||
/* The wrqu->data.length will include the null character */
|
||||
/* So, we will decrease (6 + 1) */
|
||||
wrqu->data.length -= 7;
|
||||
rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
|
||||
} else if (!memcmp(extra, "invite =", 7)) {
|
||||
} else if (!memcmp(extra, "invite=", 7)) {
|
||||
wrqu->data.length -= 8;
|
||||
rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
|
||||
} else if (!memcmp(extra, "persistent =", 11)) {
|
||||
} else if (!memcmp(extra, "persistent=", 11)) {
|
||||
wrqu->data.length -= 11;
|
||||
rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
|
||||
}
|
||||
|
@ -3887,7 +3887,7 @@ static int rtw_p2p_get(struct net_device *dev,
|
|||
"group_id", 8)) {
|
||||
rtw_p2p_get_groupid(dev, info, wrqu, extra);
|
||||
} else if (!memcmp((__force const char *)wrqu->data.pointer,
|
||||
"peer_deva_inv", 9)) {
|
||||
"peer_deva_inv", 13)) {
|
||||
/* Get the P2P device address when receiving the P2P Invitation request frame. */
|
||||
rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
|
||||
} else if (!memcmp((__force const char *)wrqu->data.pointer,
|
||||
|
@ -6920,7 +6920,7 @@ static int rtw_mp_ctx(struct net_device *dev,
|
|||
|
||||
DBG_88E("%s: in =%s\n", __func__, extra);
|
||||
|
||||
countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */
|
||||
countPkTx = strncmp(extra, "count=", 6); /* strncmp true is 0 */
|
||||
cotuTx = strncmp(extra, "background", 20);
|
||||
CarrSprTx = strncmp(extra, "background, cs", 20);
|
||||
scTx = strncmp(extra, "background, sc", 20);
|
||||
|
@ -7044,7 +7044,7 @@ static int rtw_mp_arx(struct net_device *dev,
|
|||
DBG_88E("%s: %s\n", __func__, input);
|
||||
|
||||
bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
|
||||
bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
|
||||
bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /* strncmp true is 0 */
|
||||
bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */
|
||||
|
||||
if (bStartRx) {
|
||||
|
|
|
@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
|
|||
struct sta_info *psta;
|
||||
struct sta_priv *pstapriv;
|
||||
union recv_frame *prtnframe;
|
||||
u16 ether_type = 0;
|
||||
u16 ether_type;
|
||||
|
||||
pstapriv = &adapter->stapriv;
|
||||
ptr = get_recvframe_data(precv_frame);
|
||||
|
@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
|
|||
psta = r8712_get_stainfo(pstapriv, psta_addr);
|
||||
auth_alg = adapter->securitypriv.AuthAlgrthm;
|
||||
if (auth_alg == 2) {
|
||||
/* get ether_type */
|
||||
ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
|
||||
memcpy(ðer_type, ptr, 2);
|
||||
ether_type = ntohs((unsigned short)ether_type);
|
||||
|
||||
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
|
||||
/* blocked
|
||||
* only accept EAPOL frame */
|
||||
prtnframe = precv_frame;
|
||||
/*get ether_type */
|
||||
ptr = ptr + pfhdr->attrib.hdrlen +
|
||||
pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
|
||||
memcpy(ðer_type, ptr, 2);
|
||||
ether_type = ntohs((unsigned short)ether_type);
|
||||
if (ether_type == 0x888e)
|
||||
prtnframe = precv_frame;
|
||||
else {
|
||||
|
|
|
@ -1496,45 +1496,23 @@ void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_
|
|||
int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
|
||||
{
|
||||
int match;
|
||||
uint cnt = 0;
|
||||
u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
|
||||
const u8 *ie;
|
||||
|
||||
match = false;
|
||||
match = 0;
|
||||
|
||||
if (in_len < 0) {
|
||||
if (in_len < 0)
|
||||
return match;
|
||||
}
|
||||
|
||||
while (cnt < in_len)
|
||||
{
|
||||
eid = in_ie[cnt];
|
||||
ie = cfg80211_find_vendor_ie(0x506F9A, 0x0A, in_ie, in_len);
|
||||
if (ie && (ie[1] <= (MAX_WFD_IE_LEN - 2))) {
|
||||
if (wfd_ie) {
|
||||
*wfd_ielen = ie[1] + 2;
|
||||
memcpy(wfd_ie, ie, ie[1] + 2);
|
||||
} else
|
||||
if (wfd_ielen)
|
||||
*wfd_ielen = 0;
|
||||
|
||||
if ((eid == _VENDOR_SPECIFIC_IE_) &&
|
||||
!memcmp(&in_ie[cnt+2], wfd_oui, 4)) {
|
||||
if (wfd_ie != NULL) {
|
||||
memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
|
||||
|
||||
} else {
|
||||
if (wfd_ielen != NULL) {
|
||||
*wfd_ielen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (wfd_ielen != NULL) {
|
||||
*wfd_ielen = in_ie[cnt + 1] + 2;
|
||||
}
|
||||
|
||||
cnt += in_ie[cnt + 1] + 2;
|
||||
|
||||
match = true;
|
||||
break;
|
||||
} else {
|
||||
cnt += in_ie[cnt + 1] +2; /* goto next */
|
||||
}
|
||||
}
|
||||
|
||||
if (match == true) {
|
||||
match = cnt;
|
||||
match = 1;
|
||||
}
|
||||
|
||||
return match;
|
||||
|
|
|
@ -1281,7 +1281,7 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
|
|||
u8 p2p_status_code = P2P_STATUS_SUCCESS;
|
||||
u8 *p2pie;
|
||||
u32 p2pielen = 0;
|
||||
u8 wfd_ie[ 128 ] = { 0x00 };
|
||||
u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
|
||||
u32 wfd_ielen = 0;
|
||||
#endif /* CONFIG_8723AU_P2P */
|
||||
|
||||
|
|
|
@ -2535,7 +2535,7 @@ u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pfra
|
|||
u16 wps_devicepassword_id = 0x0000;
|
||||
uint wps_devicepassword_id_len = 0;
|
||||
#ifdef CONFIG_8723AU_P2P
|
||||
u8 wfd_ie[ 128 ] = { 0x00 };
|
||||
u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
|
||||
u32 wfd_ielen = 0;
|
||||
#endif /* CONFIG_8723AU_P2P */
|
||||
|
||||
|
@ -2741,7 +2741,7 @@ u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pfr
|
|||
u32 ies_len;
|
||||
u8 * p2p_ie;
|
||||
#ifdef CONFIG_8723AU_P2P
|
||||
u8 wfd_ie[ 128 ] = { 0x00 };
|
||||
u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
|
||||
u32 wfd_ielen = 0;
|
||||
#endif /* CONFIG_8723AU_P2P */
|
||||
|
||||
|
|
|
@ -570,7 +570,7 @@ void flush_all_cam_entry23a(struct rtw_adapter *padapter)
|
|||
int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
|
||||
{
|
||||
struct wifidirect_info *pwdinfo;
|
||||
u8 wfd_ie[128] = {0x00};
|
||||
u8 wfd_ie[MAX_WFD_IE_LEN] = {0x00};
|
||||
u32 wfd_ielen = 0;
|
||||
|
||||
pwdinfo = &padapter->wdinfo;
|
||||
|
@ -681,7 +681,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
|
|||
inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
|
||||
|
||||
if (pregpriv->wifi_spec == 1) {
|
||||
u32 j, tmp, change_inx;
|
||||
u32 j, tmp, change_inx = false;
|
||||
|
||||
/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
|
|
@ -388,7 +388,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
|
|||
|
||||
}
|
||||
|
||||
static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
|
||||
static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
|
@ -410,6 +410,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
|
|||
rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name);
|
||||
#endif
|
||||
/*<delete in kernel end>*/
|
||||
if (!rtlpriv->works.rtl_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
|
||||
(void *)rtl_watchdog_wq_callback);
|
||||
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
|
||||
|
@ -421,6 +424,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
|
|||
INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
|
||||
(void *)rtl_fwevt_wq_callback);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
|
||||
|
@ -519,7 +524,8 @@ int rtl_init_core(struct ieee80211_hw *hw)
|
|||
INIT_LIST_HEAD(&rtlpriv->entry_list);
|
||||
|
||||
/* <6> init deferred work */
|
||||
_rtl_init_deferred_work(hw);
|
||||
if (_rtl_init_deferred_work(hw))
|
||||
return 1;
|
||||
|
||||
/* <7> */
|
||||
#ifdef VIF_TODO
|
||||
|
|
|
@ -1855,8 +1855,9 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
|
|||
{
|
||||
static u_char goto_buf[8];
|
||||
static int num;
|
||||
int maxlen, go_pos;
|
||||
int maxlen;
|
||||
char *cp;
|
||||
|
||||
if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
|
||||
goto do_goto;
|
||||
if (type == KT_LATIN && ch == '\n')
|
||||
|
@ -1891,25 +1892,24 @@ oops:
|
|||
spk_special_handler = NULL;
|
||||
return 1;
|
||||
}
|
||||
go_pos = kstrtol(goto_buf, 10, (long *)&cp);
|
||||
goto_pos = (u_long) go_pos;
|
||||
|
||||
goto_pos = simple_strtoul(goto_buf, &cp, 10);
|
||||
|
||||
if (*cp == 'x') {
|
||||
if (*goto_buf < '0')
|
||||
goto_pos += spk_x;
|
||||
else
|
||||
else if (goto_pos > 0)
|
||||
goto_pos--;
|
||||
if (goto_pos < 0)
|
||||
goto_pos = 0;
|
||||
|
||||
if (goto_pos >= vc->vc_cols)
|
||||
goto_pos = vc->vc_cols - 1;
|
||||
goto_x = 1;
|
||||
} else {
|
||||
if (*goto_buf < '0')
|
||||
goto_pos += spk_y;
|
||||
else
|
||||
else if (goto_pos > 0)
|
||||
goto_pos--;
|
||||
if (goto_pos < 0)
|
||||
goto_pos = 0;
|
||||
|
||||
if (goto_pos >= vc->vc_rows)
|
||||
goto_pos = vc->vc_rows - 1;
|
||||
goto_x = 0;
|
||||
|
|
|
@ -381,17 +381,17 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf)
|
|||
cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
|
||||
cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
|
||||
if (!VirtControlChanFunc) {
|
||||
kfree(bus);
|
||||
LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
|
||||
POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
|
||||
POSTCODE_SEVERITY_ERR);
|
||||
kfree(bus);
|
||||
return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
|
||||
}
|
||||
if (!VirtControlChanFunc(&cmd)) {
|
||||
kfree(bus);
|
||||
LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
|
||||
POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
|
||||
POSTCODE_SEVERITY_ERR);
|
||||
kfree(bus);
|
||||
return
|
||||
CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
|
||||
}
|
||||
|
|
|
@ -104,9 +104,9 @@ finddevice(struct list_head *list, U32 busNo, U32 devNo)
|
|||
|
||||
static inline void delbusdevices(struct list_head *list, U32 busNo)
|
||||
{
|
||||
VISORCHIPSET_DEVICE_INFO *p;
|
||||
VISORCHIPSET_DEVICE_INFO *p, *tmp;
|
||||
|
||||
list_for_each_entry(p, list, entry) {
|
||||
list_for_each_entry_safe(p, tmp, list, entry) {
|
||||
if (p->busNo == busNo) {
|
||||
list_del(&p->entry);
|
||||
kfree(p);
|
||||
|
|
|
@ -605,16 +605,16 @@ EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
|
|||
static void
|
||||
cleanup_controlvm_structures(void)
|
||||
{
|
||||
VISORCHIPSET_BUS_INFO *bi;
|
||||
VISORCHIPSET_DEVICE_INFO *di;
|
||||
VISORCHIPSET_BUS_INFO *bi, *tmp_bi;
|
||||
VISORCHIPSET_DEVICE_INFO *di, *tmp_di;
|
||||
|
||||
list_for_each_entry(bi, &BusInfoList, entry) {
|
||||
list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) {
|
||||
busInfo_clear(bi);
|
||||
list_del(&bi->entry);
|
||||
kfree(bi);
|
||||
}
|
||||
|
||||
list_for_each_entry(di, &DevInfoList, entry) {
|
||||
list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) {
|
||||
devInfo_clear(di);
|
||||
list_del(&di->entry);
|
||||
kfree(di);
|
||||
|
|
|
@ -118,6 +118,7 @@ static int refresh_exported_devices(void)
|
|||
struct udev_list_entry *devices, *dev_list_entry;
|
||||
struct udev_device *dev;
|
||||
const char *path;
|
||||
const char *driver;
|
||||
|
||||
enumerate = udev_enumerate_new(udev_context);
|
||||
udev_enumerate_add_match_subsystem(enumerate, "usb");
|
||||
|
@ -128,10 +129,12 @@ static int refresh_exported_devices(void)
|
|||
udev_list_entry_foreach(dev_list_entry, devices) {
|
||||
path = udev_list_entry_get_name(dev_list_entry);
|
||||
dev = udev_device_new_from_syspath(udev_context, path);
|
||||
if (dev == NULL)
|
||||
continue;
|
||||
|
||||
/* Check whether device uses usbip-host driver. */
|
||||
if (!strcmp(udev_device_get_driver(dev),
|
||||
USBIP_HOST_DRV_NAME)) {
|
||||
driver = udev_device_get_driver(dev);
|
||||
if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
|
||||
edev = usbip_exported_device_new(path);
|
||||
if (!edev) {
|
||||
dbg("usbip_exported_device_new failed");
|
||||
|
|
|
@ -184,7 +184,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
|
|||
* @devid: unique device identifier in a remote host
|
||||
* @speed: usb device speed in a remote host
|
||||
*/
|
||||
if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 1)
|
||||
if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4)
|
||||
return -EINVAL;
|
||||
|
||||
usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
|
||||
|
|
|
@ -776,7 +776,8 @@ static int vme_user_probe(struct vme_dev *vdev)
|
|||
image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
|
||||
if (image[i].kern_buf == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto err_master_buf;
|
||||
vme_master_free(image[i].resource);
|
||||
goto err_master;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,8 +820,6 @@ static int vme_user_probe(struct vme_dev *vdev)
|
|||
|
||||
return 0;
|
||||
|
||||
/* Ensure counter set correcty to destroy all sysfs devices */
|
||||
i = VME_DEVS;
|
||||
err_sysfs:
|
||||
while (i > 0) {
|
||||
i--;
|
||||
|
@ -830,12 +829,10 @@ err_sysfs:
|
|||
|
||||
/* Ensure counter set correcty to unalloc all master windows */
|
||||
i = MASTER_MAX + 1;
|
||||
err_master_buf:
|
||||
for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
|
||||
kfree(image[i].kern_buf);
|
||||
err_master:
|
||||
while (i > MASTER_MINOR) {
|
||||
i--;
|
||||
kfree(image[i].kern_buf);
|
||||
vme_master_free(image[i].resource);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue