aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8192e/ieee80211
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/staging/rtl8192e/ieee80211
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/staging/rtl8192e/ieee80211')
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.c218
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.h102
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h2636
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c244
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h85
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c483
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c809
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c296
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_module.c352
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c2676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c3278
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c600
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c955
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c872
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h69
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h483
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c1732
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h582
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h56
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c627
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl_crypto.h399
22 files changed, 18230 insertions, 0 deletions
diff --git a/drivers/staging/rtl8192e/ieee80211/dot11d.c b/drivers/staging/rtl8192e/ieee80211/dot11d.c
new file mode 100644
index 00000000000..98e46487dc0
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/dot11d.c
@@ -0,0 +1,218 @@
1#ifdef ENABLE_DOT11D
2//-----------------------------------------------------------------------------
3// File:
4// Dot11d.c
5//
6// Description:
7// Implement 802.11d.
8//
9//-----------------------------------------------------------------------------
10
11#include "dot11d.h"
12
13void
14Dot11d_Init(struct ieee80211_device *ieee)
15{
16 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
17
18 pDot11dInfo->bEnabled = 0;
19
20 pDot11dInfo->State = DOT11D_STATE_NONE;
21 pDot11dInfo->CountryIeLen = 0;
22 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
23 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
24 RESET_CIE_WATCHDOG(ieee);
25
26 printk("Dot11d_Init()\n");
27}
28
29//
30// Description:
31// Reset to the state as we are just entering a regulatory domain.
32//
33void
34Dot11d_Reset(struct ieee80211_device *ieee)
35{
36 u32 i;
37 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
38#if 0
39 if(!pDot11dInfo->bEnabled)
40 return;
41#endif
42 // Clear old channel map
43 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
44 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
45 // Set new channel map
46 for (i=1; i<=11; i++) {
47 (pDot11dInfo->channel_map)[i] = 1;
48 }
49 for (i=12; i<=14; i++) {
50 (pDot11dInfo->channel_map)[i] = 2;
51 }
52
53 pDot11dInfo->State = DOT11D_STATE_NONE;
54 pDot11dInfo->CountryIeLen = 0;
55 RESET_CIE_WATCHDOG(ieee);
56}
57
58//
59// Description:
60// Update country IE from Beacon or Probe Resopnse
61// and configure PHY for operation in the regulatory domain.
62//
63// TODO:
64// Configure Tx power.
65//
66// Assumption:
67// 1. IS_DOT11D_ENABLE() is TRUE.
68// 2. Input IE is an valid one.
69//
70void
71Dot11d_UpdateCountryIe(
72 struct ieee80211_device *dev,
73 u8 * pTaddr,
74 u16 CoutryIeLen,
75 u8 * pCoutryIe
76 )
77{
78 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
79 u8 i, j, NumTriples, MaxChnlNum;
80 PCHNL_TXPOWER_TRIPLE pTriple;
81
82 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
83 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
84 MaxChnlNum = 0;
85 NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
86 pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
87 for(i = 0; i < NumTriples; i++)
88 {
89 if(MaxChnlNum >= pTriple->FirstChnl)
90 { // It is not in a monotonically increasing order, so stop processing.
91 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
92 return;
93 }
94 if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
95 { // It is not a valid set of channel id, so stop processing.
96 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
97 return;
98 }
99
100 for(j = 0 ; j < pTriple->NumChnls; j++)
101 {
102 pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
103 pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
104 MaxChnlNum = pTriple->FirstChnl + j;
105 }
106
107 pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
108 }
109#if 1
110 printk("Channel List:");
111 for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
112 if(pDot11dInfo->channel_map[i] > 0)
113 printk(" %d", i);
114 printk("\n");
115#endif
116
117 UPDATE_CIE_SRC(dev, pTaddr);
118
119 pDot11dInfo->CountryIeLen = CoutryIeLen;
120 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
121 pDot11dInfo->State = DOT11D_STATE_LEARNED;
122}
123
124
125u8
126DOT11D_GetMaxTxPwrInDbm(
127 struct ieee80211_device *dev,
128 u8 Channel
129 )
130{
131 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
132 u8 MaxTxPwrInDbm = 255;
133
134 if(MAX_CHANNEL_NUMBER < Channel)
135 {
136 printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
137 return MaxTxPwrInDbm;
138 }
139 if(pDot11dInfo->channel_map[Channel])
140 {
141 MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
142 }
143
144 return MaxTxPwrInDbm;
145}
146
147
148void
149DOT11D_ScanComplete(
150 struct ieee80211_device * dev
151 )
152{
153 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
154
155 switch(pDot11dInfo->State)
156 {
157 case DOT11D_STATE_LEARNED:
158 pDot11dInfo->State = DOT11D_STATE_DONE;
159 break;
160
161 case DOT11D_STATE_DONE:
162 if( GET_CIE_WATCHDOG(dev) == 0 )
163 { // Reset country IE if previous one is gone.
164 Dot11d_Reset(dev);
165 }
166 break;
167 case DOT11D_STATE_NONE:
168 break;
169 }
170}
171
172int IsLegalChannel(
173 struct ieee80211_device * dev,
174 u8 channel
175)
176{
177 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
178
179 if(MAX_CHANNEL_NUMBER < channel)
180 {
181 printk("IsLegalChannel(): Invalid Channel\n");
182 return 0;
183 }
184 if(pDot11dInfo->channel_map[channel] > 0)
185 return 1;
186 return 0;
187}
188
189int ToLegalChannel(
190 struct ieee80211_device * dev,
191 u8 channel
192)
193{
194 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
195 u8 default_chn = 0;
196 u32 i = 0;
197
198 for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
199 {
200 if(pDot11dInfo->channel_map[i] > 0)
201 {
202 default_chn = i;
203 break;
204 }
205 }
206
207 if(MAX_CHANNEL_NUMBER < channel)
208 {
209 printk("IsLegalChannel(): Invalid Channel\n");
210 return default_chn;
211 }
212
213 if(pDot11dInfo->channel_map[channel] > 0)
214 return channel;
215
216 return default_chn;
217}
218#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/dot11d.h b/drivers/staging/rtl8192e/ieee80211/dot11d.h
new file mode 100644
index 00000000000..15b7a4ba37b
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/dot11d.h
@@ -0,0 +1,102 @@
1#ifndef __INC_DOT11D_H
2#define __INC_DOT11D_H
3
4#ifdef ENABLE_DOT11D
5#include "ieee80211.h"
6
7//#define ENABLE_DOT11D
8
9//#define DOT11D_MAX_CHNL_NUM 83
10
11typedef struct _CHNL_TXPOWER_TRIPLE {
12 u8 FirstChnl;
13 u8 NumChnls;
14 u8 MaxTxPowerInDbm;
15}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
16
17typedef enum _DOT11D_STATE {
18 DOT11D_STATE_NONE = 0,
19 DOT11D_STATE_LEARNED,
20 DOT11D_STATE_DONE,
21}DOT11D_STATE;
22
23typedef struct _RT_DOT11D_INFO {
24 //DECLARE_RT_OBJECT(RT_DOT11D_INFO);
25
26 bool bEnabled; // dot11MultiDomainCapabilityEnabled
27
28 u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
29 u8 CountryIeBuf[MAX_IE_LEN];
30 u8 CountryIeSrcAddr[6]; // Source AP of the country IE.
31 u8 CountryIeWatchdog;
32
33 u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
34 //u8 ChnlListLen; // #Bytes valid in ChnlList[].
35 //u8 ChnlList[DOT11D_MAX_CHNL_NUM];
36 u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
37
38 DOT11D_STATE State;
39}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
40#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 )
41#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])
42#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
43
44#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
45#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
46
47#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
48#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
49
50#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
51 (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
52 FALSE : \
53 (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
54
55#define CIE_WATCHDOG_TH 1
56#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
57#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
58#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
59
60#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
61
62
63void
64Dot11d_Init(
65 struct ieee80211_device *dev
66 );
67
68void
69Dot11d_Reset(
70 struct ieee80211_device *dev
71 );
72
73void
74Dot11d_UpdateCountryIe(
75 struct ieee80211_device *dev,
76 u8 * pTaddr,
77 u16 CoutryIeLen,
78 u8 * pCoutryIe
79 );
80
81u8
82DOT11D_GetMaxTxPwrInDbm(
83 struct ieee80211_device *dev,
84 u8 Channel
85 );
86
87void
88DOT11D_ScanComplete(
89 struct ieee80211_device * dev
90 );
91
92int IsLegalChannel(
93 struct ieee80211_device * dev,
94 u8 channel
95);
96
97int ToLegalChannel(
98 struct ieee80211_device * dev,
99 u8 channel
100);
101#endif //ENABLE_DOT11D
102#endif // #ifndef __INC_DOT11D_H
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
new file mode 100644
index 00000000000..6d7963e5b6a
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -0,0 +1,2636 @@
1/*
2 * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11
3 * remains copyright by the original authors
4 *
5 * Portions of the merged code are based on Host AP (software wireless
6 * LAN access point) driver for Intersil Prism2/2.5/3.
7 *
8 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
9 * <jkmaline@cc.hut.fi>
10 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
11 *
12 * Adaption to a generic IEEE 802.11 stack by James Ketrenos
13 * <jketreno@linux.intel.com>
14 * Copyright (c) 2004, Intel Corporation
15 *
16 * Modified for Realtek's wi-fi cards by Andrea Merello
17 * <andreamrl@tiscali.it>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 2 as
21 * published by the Free Software Foundation. See README and COPYING for
22 * more details.
23 */
24#ifndef IEEE80211_H
25#define IEEE80211_H
26#include <linux/if_ether.h> /* ETH_ALEN */
27#include <linux/kernel.h> /* ARRAY_SIZE */
28#include <linux/module.h>
29#include <linux/jiffies.h>
30#include <linux/timer.h>
31#include <linux/sched.h>
32#include <linux/semaphore.h>
33#include <linux/interrupt.h>
34
35#include <linux/delay.h>
36#include <linux/wireless.h>
37
38#include "rtl819x_HT.h"
39#include "rtl819x_BA.h"
40#include "rtl819x_TS.h"
41
42#ifndef IW_MODE_MONITOR
43#define IW_MODE_MONITOR 6
44#endif
45
46#ifndef IWEVCUSTOM
47#define IWEVCUSTOM 0x8c02
48#endif
49
50#ifndef container_of
51/**
52 * container_of - cast a member of a structure out to the containing structure
53 *
54 * @ptr: the pointer to the member.
55 * @type: the type of the container struct this is embedded in.
56 * @member: the name of the member within the struct.
57 *
58 */
59#define container_of(ptr, type, member) ({ \
60 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
61 (type *)( (char *)__mptr - offsetof(type,member) );})
62#endif
63
64#define KEY_TYPE_NA 0x0
65#define KEY_TYPE_WEP40 0x1
66#define KEY_TYPE_TKIP 0x2
67#define KEY_TYPE_CCMP 0x4
68#define KEY_TYPE_WEP104 0x5
69
70/* added for rtl819x tx procedure */
71#define MAX_QUEUE_SIZE 0x10
72
73//
74// 8190 queue mapping
75//
76#define BK_QUEUE 0
77#define BE_QUEUE 1
78#define VI_QUEUE 2
79#define VO_QUEUE 3
80#define HCCA_QUEUE 4
81#define TXCMD_QUEUE 5
82#define MGNT_QUEUE 6
83#define HIGH_QUEUE 7
84#define BEACON_QUEUE 8
85
86#define LOW_QUEUE BE_QUEUE
87#define NORMAL_QUEUE MGNT_QUEUE
88
89//added by amy for ps
90#define SWRF_TIMEOUT 50
91
92//added by amy for LEAP related
93#define IE_CISCO_FLAG_POSITION 0x08 // Flag byte: byte 8, numbered from 0.
94#define SUPPORT_CKIP_MIC 0x08 // bit3
95#define SUPPORT_CKIP_PK 0x10 // bit4
96/* defined for skb cb field */
97/* At most 28 byte */
98typedef struct cb_desc {
99 /* Tx Desc Related flags (8-9) */
100 u8 bLastIniPkt:1;
101 u8 bCmdOrInit:1;
102 u8 bFirstSeg:1;
103 u8 bLastSeg:1;
104 u8 bEncrypt:1;
105 u8 bTxDisableRateFallBack:1;
106 u8 bTxUseDriverAssingedRate:1;
107 u8 bHwSec:1; //indicate whether use Hw security. WB
108
109 u8 reserved1;
110
111 /* Tx Firmware Relaged flags (10-11)*/
112 u8 bCTSEnable:1;
113 u8 bRTSEnable:1;
114 u8 bUseShortGI:1;
115 u8 bUseShortPreamble:1;
116 u8 bTxEnableFwCalcDur:1;
117 u8 bAMPDUEnable:1;
118 u8 bRTSSTBC:1;
119 u8 RTSSC:1;
120
121 u8 bRTSBW:1;
122 u8 bPacketBW:1;
123 u8 bRTSUseShortPreamble:1;
124 u8 bRTSUseShortGI:1;
125 u8 bMulticast:1;
126 u8 bBroadcast:1;
127 //u8 reserved2:2;
128 u8 drv_agg_enable:1;
129 u8 reserved2:1;
130
131 /* Tx Desc related element(12-19) */
132 u8 rata_index;
133 u8 queue_index;
134 //u8 reserved3;
135 //u8 reserved4;
136 u16 txbuf_size;
137 //u8 reserved5;
138 u8 RATRIndex;
139 u8 reserved6;
140 u8 reserved7;
141 u8 reserved8;
142
143 /* Tx firmware related element(20-27) */
144 u8 data_rate;
145 u8 rts_rate;
146 u8 ampdu_factor;
147 u8 ampdu_density;
148 //u8 reserved9;
149 //u8 reserved10;
150 //u8 reserved11;
151 u8 DrvAggrNum;
152 u16 pkt_size;
153 u8 reserved12;
154
155 u8 bdhcp;
156}cb_desc, *pcb_desc;
157
158/*--------------------------Define -------------------------------------------*/
159#define MGN_1M 0x02
160#define MGN_2M 0x04
161#define MGN_5_5M 0x0b
162#define MGN_11M 0x16
163
164#define MGN_6M 0x0c
165#define MGN_9M 0x12
166#define MGN_12M 0x18
167#define MGN_18M 0x24
168#define MGN_24M 0x30
169#define MGN_36M 0x48
170#define MGN_48M 0x60
171#define MGN_54M 0x6c
172
173#define MGN_MCS0 0x80
174#define MGN_MCS1 0x81
175#define MGN_MCS2 0x82
176#define MGN_MCS3 0x83
177#define MGN_MCS4 0x84
178#define MGN_MCS5 0x85
179#define MGN_MCS6 0x86
180#define MGN_MCS7 0x87
181#define MGN_MCS8 0x88
182#define MGN_MCS9 0x89
183#define MGN_MCS10 0x8a
184#define MGN_MCS11 0x8b
185#define MGN_MCS12 0x8c
186#define MGN_MCS13 0x8d
187#define MGN_MCS14 0x8e
188#define MGN_MCS15 0x8f
189
190//----------------------------------------------------------------------------
191// 802.11 Management frame Reason Code field
192//----------------------------------------------------------------------------
193enum _ReasonCode{
194 unspec_reason = 0x1,
195 auth_not_valid = 0x2,
196 deauth_lv_ss = 0x3,
197 inactivity = 0x4,
198 ap_overload = 0x5,
199 class2_err = 0x6,
200 class3_err = 0x7,
201 disas_lv_ss = 0x8,
202 asoc_not_auth = 0x9,
203
204 //----MIC_CHECK
205 mic_failure = 0xe,
206 //----END MIC_CHECK
207
208 // Reason code defined in 802.11i D10.0 p.28.
209 invalid_IE = 0x0d,
210 four_way_tmout = 0x0f,
211 two_way_tmout = 0x10,
212 IE_dismatch = 0x11,
213 invalid_Gcipher = 0x12,
214 invalid_Pcipher = 0x13,
215 invalid_AKMP = 0x14,
216 unsup_RSNIEver = 0x15,
217 invalid_RSNIE = 0x16,
218 auth_802_1x_fail= 0x17,
219 ciper_reject = 0x18,
220
221 // Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15.
222 QoS_unspec = 0x20, // 32
223 QAP_bandwidth = 0x21, // 33
224 poor_condition = 0x22, // 34
225 no_facility = 0x23, // 35
226 // Where is 36???
227 req_declined = 0x25, // 37
228 invalid_param = 0x26, // 38
229 req_not_honored= 0x27, // 39
230 TS_not_created = 0x2F, // 47
231 DL_not_allowed = 0x30, // 48
232 dest_not_exist = 0x31, // 49
233 dest_not_QSTA = 0x32, // 50
234};
235
236
237
238#define aSifsTime (((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10)
239
240#define MGMT_QUEUE_NUM 5
241
242#define IEEE_CMD_SET_WPA_PARAM 1
243#define IEEE_CMD_SET_WPA_IE 2
244#define IEEE_CMD_SET_ENCRYPTION 3
245#define IEEE_CMD_MLME 4
246
247#define IEEE_PARAM_WPA_ENABLED 1
248#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
249#define IEEE_PARAM_DROP_UNENCRYPTED 3
250#define IEEE_PARAM_PRIVACY_INVOKED 4
251#define IEEE_PARAM_AUTH_ALGS 5
252#define IEEE_PARAM_IEEE_802_1X 6
253//It should consistent with the driver_XXX.c
254// David, 2006.9.26
255#define IEEE_PARAM_WPAX_SELECT 7
256//Added for notify the encryption type selection
257// David, 2006.9.26
258#define IEEE_PROTO_WPA 1
259#define IEEE_PROTO_RSN 2
260//Added for notify the encryption type selection
261// David, 2006.9.26
262#define IEEE_WPAX_USEGROUP 0
263#define IEEE_WPAX_WEP40 1
264#define IEEE_WPAX_TKIP 2
265#define IEEE_WPAX_WRAP 3
266#define IEEE_WPAX_CCMP 4
267#define IEEE_WPAX_WEP104 5
268
269#define IEEE_KEY_MGMT_IEEE8021X 1
270#define IEEE_KEY_MGMT_PSK 2
271
272#define IEEE_MLME_STA_DEAUTH 1
273#define IEEE_MLME_STA_DISASSOC 2
274
275
276#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
277#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
278#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
279#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
280#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
281#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
282
283
284#define IEEE_CRYPT_ALG_NAME_LEN 16
285
286#define MAX_IE_LEN 0xff
287
288// added for kernel conflict
289#define ieee80211_crypt_deinit_entries ieee80211_crypt_deinit_entries_rsl
290#define ieee80211_crypt_deinit_handler ieee80211_crypt_deinit_handler_rsl
291#define ieee80211_crypt_delayed_deinit ieee80211_crypt_delayed_deinit_rsl
292#define ieee80211_register_crypto_ops ieee80211_register_crypto_ops_rsl
293#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rsl
294#define ieee80211_get_crypto_ops ieee80211_get_crypto_ops_rsl
295
296#define ieee80211_ccmp_null ieee80211_ccmp_null_rsl
297
298#define ieee80211_tkip_null ieee80211_tkip_null_rsl
299
300#define ieee80211_wep_null ieee80211_wep_null_rsl
301
302#define free_ieee80211 free_ieee80211_rsl
303#define alloc_ieee80211 alloc_ieee80211_rsl
304
305#define ieee80211_rx ieee80211_rx_rsl
306#define ieee80211_rx_mgt ieee80211_rx_mgt_rsl
307
308#define ieee80211_get_beacon ieee80211_get_beacon_rsl
309#define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl
310#define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl
311#define ieee80211_reset_queue ieee80211_reset_queue_rsl
312#define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl
313#define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
314#define ieee80211_is_shortslot ieee80211_is_shortslot_rsl
315#define ieee80211_is_54g ieee80211_is_54g_rsl
316#define ieee80211_wpa_supplicant_ioctl ieee80211_wpa_supplicant_ioctl_rsl
317#define ieee80211_ps_tx_ack ieee80211_ps_tx_ack_rsl
318#define ieee80211_softmac_xmit ieee80211_softmac_xmit_rsl
319#define ieee80211_stop_send_beacons ieee80211_stop_send_beacons_rsl
320#define notify_wx_assoc_event notify_wx_assoc_event_rsl
321#define SendDisassociation SendDisassociation_rsl
322#define ieee80211_disassociate ieee80211_disassociate_rsl
323#define ieee80211_start_send_beacons ieee80211_start_send_beacons_rsl
324#define ieee80211_stop_scan ieee80211_stop_scan_rsl
325#define ieee80211_send_probe_requests ieee80211_send_probe_requests_rsl
326#define ieee80211_softmac_scan_syncro ieee80211_softmac_scan_syncro_rsl
327#define ieee80211_start_scan_syncro ieee80211_start_scan_syncro_rsl
328
329#define ieee80211_wx_get_essid ieee80211_wx_get_essid_rsl
330#define ieee80211_wx_set_essid ieee80211_wx_set_essid_rsl
331#define ieee80211_wx_set_rate ieee80211_wx_set_rate_rsl
332#define ieee80211_wx_get_rate ieee80211_wx_get_rate_rsl
333#define ieee80211_wx_set_wap ieee80211_wx_set_wap_rsl
334#define ieee80211_wx_get_wap ieee80211_wx_get_wap_rsl
335#define ieee80211_wx_set_mode ieee80211_wx_set_mode_rsl
336#define ieee80211_wx_get_mode ieee80211_wx_get_mode_rsl
337#define ieee80211_wx_set_scan ieee80211_wx_set_scan_rsl
338#define ieee80211_wx_get_freq ieee80211_wx_get_freq_rsl
339#define ieee80211_wx_set_freq ieee80211_wx_set_freq_rsl
340#define ieee80211_wx_set_rawtx ieee80211_wx_set_rawtx_rsl
341#define ieee80211_wx_get_name ieee80211_wx_get_name_rsl
342#define ieee80211_wx_set_power ieee80211_wx_set_power_rsl
343#define ieee80211_wx_get_power ieee80211_wx_get_power_rsl
344#define ieee80211_wlan_frequencies ieee80211_wlan_frequencies_rsl
345#define ieee80211_wx_set_rts ieee80211_wx_set_rts_rsl
346#define ieee80211_wx_get_rts ieee80211_wx_get_rts_rsl
347
348#define ieee80211_txb_free ieee80211_txb_free_rsl
349
350#define ieee80211_wx_set_gen_ie ieee80211_wx_set_gen_ie_rsl
351#define ieee80211_wx_get_scan ieee80211_wx_get_scan_rsl
352#define ieee80211_wx_set_encode ieee80211_wx_set_encode_rsl
353#define ieee80211_wx_get_encode ieee80211_wx_get_encode_rsl
354#define ieee80211_wx_set_mlme ieee80211_wx_set_mlme_rsl
355#define ieee80211_wx_set_auth ieee80211_wx_set_auth_rsl
356#define ieee80211_wx_set_encode_ext ieee80211_wx_set_encode_ext_rsl
357#define ieee80211_wx_get_encode_ext ieee80211_wx_get_encode_ext_rsl
358
359
360typedef struct ieee_param {
361 u32 cmd;
362 u8 sta_addr[ETH_ALEN];
363 union {
364 struct {
365 u8 name;
366 u32 value;
367 } wpa_param;
368 struct {
369 u32 len;
370 u8 reserved[32];
371 u8 data[0];
372 } wpa_ie;
373 struct{
374 int command;
375 int reason_code;
376 } mlme;
377 struct {
378 u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
379 u8 set_tx;
380 u32 err;
381 u8 idx;
382 u8 seq[8]; /* sequence counter (set: RX, get: TX) */
383 u16 key_len;
384 u8 key[0];
385 } crypt;
386 } u;
387}ieee_param;
388
389
390// linux under 2.6.9 release may not support it, so modify it for common use
391#define MSECS(t) msecs_to_jiffies(t)
392#define msleep_interruptible_rsl msleep_interruptible
393
394#define IEEE80211_DATA_LEN 2304
395/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
396 6.2.1.1.2.
397
398 The figure in section 7.1.2 suggests a body size of up to 2312
399 bytes is allowed, which is a bit confusing, I suspect this
400 represents the 2304 bytes of real data, plus a possible 8 bytes of
401 WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
402#define IEEE80211_1ADDR_LEN 10
403#define IEEE80211_2ADDR_LEN 16
404#define IEEE80211_3ADDR_LEN 24
405#define IEEE80211_4ADDR_LEN 30
406#define IEEE80211_FCS_LEN 4
407#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
408#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
409#define IEEE80211_MGMT_HDR_LEN 24
410#define IEEE80211_DATA_HDR3_LEN 24
411#define IEEE80211_DATA_HDR4_LEN 30
412
413#define MIN_FRAG_THRESHOLD 256U
414#define MAX_FRAG_THRESHOLD 2346U
415
416
417/* Frame control field constants */
418#define IEEE80211_FCTL_VERS 0x0003
419#define IEEE80211_FCTL_FTYPE 0x000c
420#define IEEE80211_FCTL_STYPE 0x00f0
421#define IEEE80211_FCTL_FRAMETYPE 0x00fc
422#define IEEE80211_FCTL_TODS 0x0100
423#define IEEE80211_FCTL_FROMDS 0x0200
424#define IEEE80211_FCTL_DSTODS 0x0300 //added by david
425#define IEEE80211_FCTL_MOREFRAGS 0x0400
426#define IEEE80211_FCTL_RETRY 0x0800
427#define IEEE80211_FCTL_PM 0x1000
428#define IEEE80211_FCTL_MOREDATA 0x2000
429#define IEEE80211_FCTL_WEP 0x4000
430#define IEEE80211_FCTL_ORDER 0x8000
431
432#define IEEE80211_FTYPE_MGMT 0x0000
433#define IEEE80211_FTYPE_CTL 0x0004
434#define IEEE80211_FTYPE_DATA 0x0008
435
436/* management */
437#define IEEE80211_STYPE_ASSOC_REQ 0x0000
438#define IEEE80211_STYPE_ASSOC_RESP 0x0010
439#define IEEE80211_STYPE_REASSOC_REQ 0x0020
440#define IEEE80211_STYPE_REASSOC_RESP 0x0030
441#define IEEE80211_STYPE_PROBE_REQ 0x0040
442#define IEEE80211_STYPE_PROBE_RESP 0x0050
443#define IEEE80211_STYPE_BEACON 0x0080
444#define IEEE80211_STYPE_ATIM 0x0090
445#define IEEE80211_STYPE_DISASSOC 0x00A0
446#define IEEE80211_STYPE_AUTH 0x00B0
447#define IEEE80211_STYPE_DEAUTH 0x00C0
448#define IEEE80211_STYPE_MANAGE_ACT 0x00D0
449
450/* control */
451#define IEEE80211_STYPE_PSPOLL 0x00A0
452#define IEEE80211_STYPE_RTS 0x00B0
453#define IEEE80211_STYPE_CTS 0x00C0
454#define IEEE80211_STYPE_ACK 0x00D0
455#define IEEE80211_STYPE_CFEND 0x00E0
456#define IEEE80211_STYPE_CFENDACK 0x00F0
457#define IEEE80211_STYPE_BLOCKACK 0x0094
458
459/* data */
460#define IEEE80211_STYPE_DATA 0x0000
461#define IEEE80211_STYPE_DATA_CFACK 0x0010
462#define IEEE80211_STYPE_DATA_CFPOLL 0x0020
463#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
464#define IEEE80211_STYPE_NULLFUNC 0x0040
465#define IEEE80211_STYPE_CFACK 0x0050
466#define IEEE80211_STYPE_CFPOLL 0x0060
467#define IEEE80211_STYPE_CFACKPOLL 0x0070
468#define IEEE80211_STYPE_QOS_DATA 0x0080 //added for WMM 2006/8/2
469#define IEEE80211_STYPE_QOS_NULL 0x00C0
470
471#define IEEE80211_SCTL_FRAG 0x000F
472#define IEEE80211_SCTL_SEQ 0xFFF0
473
474/* QOS control */
475#define IEEE80211_QCTL_TID 0x000F
476
477#define FC_QOS_BIT BIT7
478#define IsDataFrame(pdu) ( ((pdu[0] & 0x0C)==0x08) ? true : false )
479#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) )
480//added by wb. Is this right?
481#define IsQoSDataFrame(pframe) ((*(u16*)pframe&(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) == (IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA))
482#define Frame_Order(pframe) (*(u16*)pframe&IEEE80211_FCTL_ORDER)
483#define SN_LESS(a, b) (((a-b)&0x800)!=0)
484#define SN_EQUAL(a, b) (a == b)
485#define MAX_DEV_ADDR_SIZE 8
486typedef enum _ACT_CATEGORY{
487 ACT_CAT_QOS = 1,
488 ACT_CAT_DLS = 2,
489 ACT_CAT_BA = 3,
490 ACT_CAT_HT = 7,
491 ACT_CAT_WMM = 17,
492} ACT_CATEGORY, *PACT_CATEGORY;
493
494typedef enum _TS_ACTION{
495 ACT_ADDTSREQ = 0,
496 ACT_ADDTSRSP = 1,
497 ACT_DELTS = 2,
498 ACT_SCHEDULE = 3,
499} TS_ACTION, *PTS_ACTION;
500
501typedef enum _BA_ACTION{
502 ACT_ADDBAREQ = 0,
503 ACT_ADDBARSP = 1,
504 ACT_DELBA = 2,
505} BA_ACTION, *PBA_ACTION;
506
507typedef enum _InitialGainOpType{
508 IG_Backup=0,
509 IG_Restore,
510 IG_Max
511}InitialGainOpType;
512
513/* debug macros */
514#define CONFIG_IEEE80211_DEBUG
515#ifdef CONFIG_IEEE80211_DEBUG
516extern u32 ieee80211_debug_level;
517#define IEEE80211_DEBUG(level, fmt, args...) \
518do { if (ieee80211_debug_level & (level)) \
519 printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0)
520//wb added to debug out data buf
521//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA
522#define IEEE80211_DEBUG_DATA(level, data, datalen) \
523 do{ if ((ieee80211_debug_level & (level)) == (level)) \
524 { \
525 int i; \
526 u8* pdata = (u8*) data; \
527 printk(KERN_DEBUG "ieee80211: %s()\n", __FUNCTION__); \
528 for(i=0; i<(int)(datalen); i++) \
529 { \
530 printk("%2x ", pdata[i]); \
531 if ((i+1)%16 == 0) printk("\n"); \
532 } \
533 printk("\n"); \
534 } \
535 } while (0)
536#else
537#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
538#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0)
539#endif /* CONFIG_IEEE80211_DEBUG */
540
541/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
542
543/*
544 * To use the debug system;
545 *
546 * If you are defining a new debug classification, simply add it to the #define
547 * list here in the form of:
548 *
549 * #define IEEE80211_DL_xxxx VALUE
550 *
551 * shifting value to the left one bit from the previous entry. xxxx should be
552 * the name of the classification (for example, WEP)
553 *
554 * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
555 * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
556 * to send output to that classification.
557 *
558 * To add your debug level to the list of levels seen when you perform
559 *
560 * % cat /proc/net/ipw/debug_level
561 *
562 * you simply need to add your entry to the ipw_debug_levels array.
563 *
564 * If you do not see debug_level in /proc/net/ipw then you do not have
565 * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
566 *
567 */
568
569#define IEEE80211_DL_INFO (1<<0)
570#define IEEE80211_DL_WX (1<<1)
571#define IEEE80211_DL_SCAN (1<<2)
572#define IEEE80211_DL_STATE (1<<3)
573#define IEEE80211_DL_MGMT (1<<4)
574#define IEEE80211_DL_FRAG (1<<5)
575#define IEEE80211_DL_EAP (1<<6)
576#define IEEE80211_DL_DROP (1<<7)
577
578#define IEEE80211_DL_TX (1<<8)
579#define IEEE80211_DL_RX (1<<9)
580
581#define IEEE80211_DL_HT (1<<10) //HT
582#define IEEE80211_DL_BA (1<<11) //ba
583#define IEEE80211_DL_TS (1<<12) //TS
584#define IEEE80211_DL_QOS (1<<13)
585#define IEEE80211_DL_REORDER (1<<14)
586#define IEEE80211_DL_IOT (1<<15)
587#define IEEE80211_DL_IPS (1<<16)
588#define IEEE80211_DL_TRACE (1<<29) //trace function, need to user net_ratelimit() together in order not to print too much to the screen
589#define IEEE80211_DL_DATA (1<<30) //use this flag to control whether print data buf out.
590#define IEEE80211_DL_ERR (1<<31) //always open
591#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
592#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
593#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
594
595#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
596#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
597#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
598#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
599#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
600#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
601#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
602#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
603#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
604#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
605
606#ifdef CONFIG_IEEE80211_DEBUG
607/* Added by Annie, 2005-11-22. */
608#define MAX_STR_LEN 64
609/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/
610#define PRINTABLE(_ch) (_ch>'!' && _ch<'~')
611#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) \
612 if((_Comp) & level) \
613 { \
614 int __i; \
615 u8 buffer[MAX_STR_LEN]; \
616 int length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ; \
617 memset(buffer, 0, MAX_STR_LEN); \
618 memcpy(buffer, (u8 *)_Ptr, length ); \
619 for( __i=0; __i<MAX_STR_LEN; __i++ ) \
620 { \
621 if( !PRINTABLE(buffer[__i]) ) buffer[__i] = '?'; \
622 } \
623 buffer[length] = '\0'; \
624 printk("Rtl819x: "); \
625 printk(_TitleString); \
626 printk(": %d, <%s>\n", _Len, buffer); \
627 }
628#else
629#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) do {} while (0)
630#endif
631
632#include <linux/netdevice.h>
633#include <linux/if_arp.h> /* ARPHRD_ETHER */
634
635#ifndef WIRELESS_SPY
636#define WIRELESS_SPY // enable iwspy support
637#endif
638#include <net/iw_handler.h> // new driver API
639
640#ifndef ETH_P_PAE
641#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
642#endif /* ETH_P_PAE */
643
644#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
645
646#ifndef ETH_P_80211_RAW
647#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
648#endif
649
650/* IEEE 802.11 defines */
651
652#define P80211_OUI_LEN 3
653
654struct ieee80211_snap_hdr {
655
656 u8 dsap; /* always 0xAA */
657 u8 ssap; /* always 0xAA */
658 u8 ctrl; /* always 0x03 */
659 u8 oui[P80211_OUI_LEN]; /* organizational universal id */
660
661} __attribute__ ((packed));
662
663#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
664
665#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
666#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
667#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
668#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA)
669
670
671#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
672#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
673#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
674
675/* Authentication algorithms */
676#define WLAN_AUTH_OPEN 0
677#define WLAN_AUTH_SHARED_KEY 1
678#define WLAN_AUTH_LEAP 2
679
680#define WLAN_AUTH_CHALLENGE_LEN 128
681
682#define WLAN_CAPABILITY_BSS (1<<0)
683#define WLAN_CAPABILITY_IBSS (1<<1)
684#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
685#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
686#define WLAN_CAPABILITY_PRIVACY (1<<4)
687#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
688#define WLAN_CAPABILITY_PBCC (1<<6)
689#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
690#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
691#define WLAN_CAPABILITY_QOS (1<<9)
692#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
693#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
694
695/* 802.11g ERP information element */
696#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
697#define WLAN_ERP_USE_PROTECTION (1<<1)
698#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
699
700/* Status codes */
701enum ieee80211_statuscode {
702 WLAN_STATUS_SUCCESS = 0,
703 WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
704 WLAN_STATUS_CAPS_UNSUPPORTED = 10,
705 WLAN_STATUS_REASSOC_NO_ASSOC = 11,
706 WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
707 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
708 WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
709 WLAN_STATUS_CHALLENGE_FAIL = 15,
710 WLAN_STATUS_AUTH_TIMEOUT = 16,
711 WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
712 WLAN_STATUS_ASSOC_DENIED_RATES = 18,
713 /* 802.11b */
714 WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
715 WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
716 WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
717 /* 802.11h */
718 WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
719 WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
720 WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
721 /* 802.11g */
722 WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
723 WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
724 /* 802.11i */
725 WLAN_STATUS_INVALID_IE = 40,
726 WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
727 WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
728 WLAN_STATUS_INVALID_AKMP = 43,
729 WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
730 WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
731 WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
732};
733
734/* Reason codes */
735enum ieee80211_reasoncode {
736 WLAN_REASON_UNSPECIFIED = 1,
737 WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
738 WLAN_REASON_DEAUTH_LEAVING = 3,
739 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
740 WLAN_REASON_DISASSOC_AP_BUSY = 5,
741 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
742 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
743 WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
744 WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
745 /* 802.11h */
746 WLAN_REASON_DISASSOC_BAD_POWER = 10,
747 WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
748 /* 802.11i */
749 WLAN_REASON_INVALID_IE = 13,
750 WLAN_REASON_MIC_FAILURE = 14,
751 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
752 WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
753 WLAN_REASON_IE_DIFFERENT = 17,
754 WLAN_REASON_INVALID_GROUP_CIPHER = 18,
755 WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
756 WLAN_REASON_INVALID_AKMP = 20,
757 WLAN_REASON_UNSUPP_RSN_VERSION = 21,
758 WLAN_REASON_INVALID_RSN_IE_CAP = 22,
759 WLAN_REASON_IEEE8021X_FAILED = 23,
760 WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
761};
762
763#define IEEE80211_STATMASK_SIGNAL (1<<0)
764#define IEEE80211_STATMASK_RSSI (1<<1)
765#define IEEE80211_STATMASK_NOISE (1<<2)
766#define IEEE80211_STATMASK_RATE (1<<3)
767#define IEEE80211_STATMASK_WEMASK 0x7
768
769#define IEEE80211_CCK_MODULATION (1<<0)
770#define IEEE80211_OFDM_MODULATION (1<<1)
771
772#define IEEE80211_24GHZ_BAND (1<<0)
773#define IEEE80211_52GHZ_BAND (1<<1)
774
775#define IEEE80211_CCK_RATE_LEN 4
776#define IEEE80211_CCK_RATE_1MB 0x02
777#define IEEE80211_CCK_RATE_2MB 0x04
778#define IEEE80211_CCK_RATE_5MB 0x0B
779#define IEEE80211_CCK_RATE_11MB 0x16
780#define IEEE80211_OFDM_RATE_LEN 8
781#define IEEE80211_OFDM_RATE_6MB 0x0C
782#define IEEE80211_OFDM_RATE_9MB 0x12
783#define IEEE80211_OFDM_RATE_12MB 0x18
784#define IEEE80211_OFDM_RATE_18MB 0x24
785#define IEEE80211_OFDM_RATE_24MB 0x30
786#define IEEE80211_OFDM_RATE_36MB 0x48
787#define IEEE80211_OFDM_RATE_48MB 0x60
788#define IEEE80211_OFDM_RATE_54MB 0x6C
789#define IEEE80211_BASIC_RATE_MASK 0x80
790
791#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
792#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
793#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
794#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
795#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
796#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
797#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
798#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
799#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
800#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
801#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
802#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
803
804#define IEEE80211_CCK_RATES_MASK 0x0000000F
805#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
806 IEEE80211_CCK_RATE_2MB_MASK)
807#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \
808 IEEE80211_CCK_RATE_5MB_MASK | \
809 IEEE80211_CCK_RATE_11MB_MASK)
810
811#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
812#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
813 IEEE80211_OFDM_RATE_12MB_MASK | \
814 IEEE80211_OFDM_RATE_24MB_MASK)
815#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \
816 IEEE80211_OFDM_RATE_9MB_MASK | \
817 IEEE80211_OFDM_RATE_18MB_MASK | \
818 IEEE80211_OFDM_RATE_36MB_MASK | \
819 IEEE80211_OFDM_RATE_48MB_MASK | \
820 IEEE80211_OFDM_RATE_54MB_MASK)
821#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
822 IEEE80211_CCK_DEFAULT_RATES_MASK)
823
824#define IEEE80211_NUM_OFDM_RATES 8
825#define IEEE80211_NUM_CCK_RATES 4
826#define IEEE80211_OFDM_SHIFT_MASK_A 4
827
828
829/* this is stolen and modified from the madwifi driver*/
830#define IEEE80211_FC0_TYPE_MASK 0x0c
831#define IEEE80211_FC0_TYPE_DATA 0x08
832#define IEEE80211_FC0_SUBTYPE_MASK 0xB0
833#define IEEE80211_FC0_SUBTYPE_QOS 0x80
834
835#define IEEE80211_QOS_HAS_SEQ(fc) \
836 (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \
837 (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
838
839/* this is stolen from ipw2200 driver */
840#define IEEE_IBSS_MAC_HASH_SIZE 31
841struct ieee_ibss_seq {
842 u8 mac[ETH_ALEN];
843 u16 seq_num[17];
844 u16 frag_num[17];
845 unsigned long packet_time[17];
846 struct list_head list;
847};
848
849/* NOTE: This data is for statistical purposes; not all hardware provides this
850 * information for frames received. Not setting these will not cause
851 * any adverse affects. */
852struct ieee80211_rx_stats {
853 u32 mac_time[2];
854 s8 rssi;
855 u8 signal;
856 u8 noise;
857 u16 rate; /* in 100 kbps */
858 u8 received_channel;
859 u8 control;
860 u8 mask;
861 u8 freq;
862 u16 len;
863 u64 tsf;
864 u32 beacon_time;
865 u8 nic_type;
866 u16 Length;
867 u8 SignalQuality; // in 0-100 index.
868 s32 RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation.
869 s8 RxPower; // in dBm Translate from PWdB
870 u8 SignalStrength; // in 0-100 index.
871 u16 bHwError:1;
872 u16 bCRC:1;
873 u16 bICV:1;
874 u16 bShortPreamble:1;
875 u16 Antenna:1; //for rtl8185
876 u16 Decrypted:1; //for rtl8185, rtl8187
877 u16 Wakeup:1; //for rtl8185
878 u16 Reserved0:1; //for rtl8185
879 u8 AGC;
880 u32 TimeStampLow;
881 u32 TimeStampHigh;
882 bool bShift;
883 bool bIsQosData; // Added by Annie, 2005-12-22.
884 u8 UserPriority;
885
886 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
887 //1Attention Please!!!<11n or 8190 specific code should be put below this line>
888 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
889
890 u8 RxDrvInfoSize;
891 u8 RxBufShift;
892 bool bIsAMPDU;
893 bool bFirstMPDU;
894 bool bContainHTC;
895 u32 RxPWDBAll;
896 u8 RxMIMOSignalStrength[4]; // in 0~100 index
897 s8 RxMIMOSignalQuality[2];
898 bool bPacketMatchBSSID;
899 bool bIsCCK;
900 bool bPacketToSelf;
901 u8* virtual_address;
902 bool bPacketBeacon; //cosa add for rssi
903 bool bToSelfBA; //cosa add for rssi
904 char cck_adc_pwdb[4]; //cosa add for rx path selection
905};
906
907/* IEEE 802.11 requires that STA supports concurrent reception of at least
908 * three fragmented frames. This define can be increased to support more
909 * concurrent frames, but it should be noted that each entry can consume about
910 * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
911#define IEEE80211_FRAG_CACHE_LEN 4
912
913struct ieee80211_frag_entry {
914 unsigned long first_frag_time;
915 unsigned int seq;
916 unsigned int last_frag;
917 struct sk_buff *skb;
918 u8 src_addr[ETH_ALEN];
919 u8 dst_addr[ETH_ALEN];
920};
921
922struct ieee80211_stats {
923 unsigned int tx_unicast_frames;
924 unsigned int tx_multicast_frames;
925 unsigned int tx_fragments;
926 unsigned int tx_unicast_octets;
927 unsigned int tx_multicast_octets;
928 unsigned int tx_deferred_transmissions;
929 unsigned int tx_single_retry_frames;
930 unsigned int tx_multiple_retry_frames;
931 unsigned int tx_retry_limit_exceeded;
932 unsigned int tx_discards;
933 unsigned int rx_unicast_frames;
934 unsigned int rx_multicast_frames;
935 unsigned int rx_fragments;
936 unsigned int rx_unicast_octets;
937 unsigned int rx_multicast_octets;
938 unsigned int rx_fcs_errors;
939 unsigned int rx_discards_no_buffer;
940 unsigned int tx_discards_wrong_sa;
941 unsigned int rx_discards_undecryptable;
942 unsigned int rx_message_in_msg_fragments;
943 unsigned int rx_message_in_bad_msg_fragments;
944};
945
946struct ieee80211_device;
947
948#include "ieee80211_crypt.h"
949
950#define SEC_KEY_1 (1<<0)
951#define SEC_KEY_2 (1<<1)
952#define SEC_KEY_3 (1<<2)
953#define SEC_KEY_4 (1<<3)
954#define SEC_ACTIVE_KEY (1<<4)
955#define SEC_AUTH_MODE (1<<5)
956#define SEC_UNICAST_GROUP (1<<6)
957#define SEC_LEVEL (1<<7)
958#define SEC_ENABLED (1<<8)
959#define SEC_ENCRYPT (1<<9)
960
961#define SEC_LEVEL_0 0 /* None */
962#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
963#define SEC_LEVEL_2 2 /* Level 1 + TKIP */
964#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
965#define SEC_LEVEL_3 4 /* Level 2 + CCMP */
966
967#define SEC_ALG_NONE 0
968#define SEC_ALG_WEP 1
969#define SEC_ALG_TKIP 2
970#define SEC_ALG_CCMP 4
971
972#define WEP_KEYS 4
973#define WEP_KEY_LEN 13
974#define SCM_KEY_LEN 32
975#define SCM_TEMPORAL_KEY_LENGTH 16
976
977struct ieee80211_security {
978 u16 active_key:2,
979 enabled:1,
980 auth_mode:2,
981 auth_algo:4,
982 unicast_uses_group:1,
983 encrypt:1;
984 u8 key_sizes[WEP_KEYS];
985 u8 keys[WEP_KEYS][SCM_KEY_LEN];
986 u8 level;
987 u16 flags;
988} __attribute__ ((packed));
989
990
991/*
992 802.11 data frame from AP
993 ,-------------------------------------------------------------------.
994Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
995 |------|------|---------|---------|---------|------|---------|------|
996Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
997 | | tion | (BSSID) | | | ence | data | |
998 `-------------------------------------------------------------------'
999Total: 28-2340 bytes
1000*/
1001
1002/* Management Frame Information Element Types */
1003enum ieee80211_mfie {
1004 MFIE_TYPE_SSID = 0,
1005 MFIE_TYPE_RATES = 1,
1006 MFIE_TYPE_FH_SET = 2,
1007 MFIE_TYPE_DS_SET = 3,
1008 MFIE_TYPE_CF_SET = 4,
1009 MFIE_TYPE_TIM = 5,
1010 MFIE_TYPE_IBSS_SET = 6,
1011 MFIE_TYPE_COUNTRY = 7,
1012 MFIE_TYPE_HOP_PARAMS = 8,
1013 MFIE_TYPE_HOP_TABLE = 9,
1014 MFIE_TYPE_REQUEST = 10,
1015 MFIE_TYPE_CHALLENGE = 16,
1016 MFIE_TYPE_POWER_CONSTRAINT = 32,
1017 MFIE_TYPE_POWER_CAPABILITY = 33,
1018 MFIE_TYPE_TPC_REQUEST = 34,
1019 MFIE_TYPE_TPC_REPORT = 35,
1020 MFIE_TYPE_SUPP_CHANNELS = 36,
1021 MFIE_TYPE_CSA = 37,
1022 MFIE_TYPE_MEASURE_REQUEST = 38,
1023 MFIE_TYPE_MEASURE_REPORT = 39,
1024 MFIE_TYPE_QUIET = 40,
1025 MFIE_TYPE_IBSS_DFS = 41,
1026 MFIE_TYPE_ERP = 42,
1027 MFIE_TYPE_RSN = 48,
1028 MFIE_TYPE_RATES_EX = 50,
1029 MFIE_TYPE_HT_CAP= 45,
1030 MFIE_TYPE_HT_INFO= 61,
1031 MFIE_TYPE_AIRONET=133,
1032 MFIE_TYPE_GENERIC = 221,
1033 MFIE_TYPE_QOS_PARAMETER = 222,
1034};
1035
1036/* Minimal header; can be used for passing 802.11 frames with sufficient
1037 * information to determine what type of underlying data type is actually
1038 * stored in the data. */
1039 struct ieee80211_pspoll_hdr {
1040 __le16 frame_ctl;
1041 __le16 aid;
1042 u8 bssid[ETH_ALEN];
1043 u8 ta[ETH_ALEN];
1044 //u8 payload[0];
1045} __attribute__ ((packed));
1046
1047struct ieee80211_hdr {
1048 __le16 frame_ctl;
1049 __le16 duration_id;
1050 u8 payload[0];
1051} __attribute__ ((packed));
1052
1053struct ieee80211_hdr_1addr {
1054 __le16 frame_ctl;
1055 __le16 duration_id;
1056 u8 addr1[ETH_ALEN];
1057 u8 payload[0];
1058} __attribute__ ((packed));
1059
1060struct ieee80211_hdr_2addr {
1061 __le16 frame_ctl;
1062 __le16 duration_id;
1063 u8 addr1[ETH_ALEN];
1064 u8 addr2[ETH_ALEN];
1065 u8 payload[0];
1066} __attribute__ ((packed));
1067
1068struct ieee80211_hdr_3addr {
1069 __le16 frame_ctl;
1070 __le16 duration_id;
1071 u8 addr1[ETH_ALEN];
1072 u8 addr2[ETH_ALEN];
1073 u8 addr3[ETH_ALEN];
1074 __le16 seq_ctl;
1075 u8 payload[0];
1076} __attribute__ ((packed));
1077
1078struct ieee80211_hdr_4addr {
1079 __le16 frame_ctl;
1080 __le16 duration_id;
1081 u8 addr1[ETH_ALEN];
1082 u8 addr2[ETH_ALEN];
1083 u8 addr3[ETH_ALEN];
1084 __le16 seq_ctl;
1085 u8 addr4[ETH_ALEN];
1086 u8 payload[0];
1087} __attribute__ ((packed));
1088
1089struct ieee80211_hdr_3addrqos {
1090 __le16 frame_ctl;
1091 __le16 duration_id;
1092 u8 addr1[ETH_ALEN];
1093 u8 addr2[ETH_ALEN];
1094 u8 addr3[ETH_ALEN];
1095 __le16 seq_ctl;
1096 u8 payload[0];
1097 __le16 qos_ctl;
1098} __attribute__ ((packed));
1099
1100struct ieee80211_hdr_4addrqos {
1101 __le16 frame_ctl;
1102 __le16 duration_id;
1103 u8 addr1[ETH_ALEN];
1104 u8 addr2[ETH_ALEN];
1105 u8 addr3[ETH_ALEN];
1106 __le16 seq_ctl;
1107 u8 addr4[ETH_ALEN];
1108 u8 payload[0];
1109 __le16 qos_ctl;
1110} __attribute__ ((packed));
1111
1112struct ieee80211_info_element {
1113 u8 id;
1114 u8 len;
1115 u8 data[0];
1116} __attribute__ ((packed));
1117
1118struct ieee80211_authentication {
1119 struct ieee80211_hdr_3addr header;
1120 __le16 algorithm;
1121 __le16 transaction;
1122 __le16 status;
1123 /*challenge*/
1124 struct ieee80211_info_element info_element[0];
1125} __attribute__ ((packed));
1126
1127struct ieee80211_disassoc {
1128 struct ieee80211_hdr_3addr header;
1129 __le16 reason;
1130} __attribute__ ((packed));
1131
1132struct ieee80211_probe_request {
1133 struct ieee80211_hdr_3addr header;
1134 /* SSID, supported rates */
1135 struct ieee80211_info_element info_element[0];
1136} __attribute__ ((packed));
1137
1138struct ieee80211_probe_response {
1139 struct ieee80211_hdr_3addr header;
1140 u32 time_stamp[2];
1141 __le16 beacon_interval;
1142 __le16 capability;
1143 /* SSID, supported rates, FH params, DS params,
1144 * CF params, IBSS params, TIM (if beacon), RSN */
1145 struct ieee80211_info_element info_element[0];
1146} __attribute__ ((packed));
1147
1148/* Alias beacon for probe_response */
1149#define ieee80211_beacon ieee80211_probe_response
1150
1151struct ieee80211_assoc_request_frame {
1152 struct ieee80211_hdr_3addr header;
1153 __le16 capability;
1154 __le16 listen_interval;
1155 /* SSID, supported rates, RSN */
1156 struct ieee80211_info_element info_element[0];
1157} __attribute__ ((packed));
1158
1159struct ieee80211_reassoc_request_frame {
1160 struct ieee80211_hdr_3addr header;
1161 __le16 capability;
1162 __le16 listen_interval;
1163 u8 current_ap[ETH_ALEN];
1164 /* SSID, supported rates, RSN */
1165 struct ieee80211_info_element info_element[0];
1166} __attribute__ ((packed));
1167
1168struct ieee80211_assoc_response_frame {
1169 struct ieee80211_hdr_3addr header;
1170 __le16 capability;
1171 __le16 status;
1172 __le16 aid;
1173 struct ieee80211_info_element info_element[0]; /* supported rates */
1174} __attribute__ ((packed));
1175
1176struct ieee80211_txb {
1177 u8 nr_frags;
1178 u8 encrypted;
1179 u8 queue_index;
1180 u8 rts_included;
1181 u16 reserved;
1182 __le16 frag_size;
1183 __le16 payload_size;
1184 struct sk_buff *fragments[0];
1185};
1186
1187#define MAX_TX_AGG_COUNT 16
1188struct ieee80211_drv_agg_txb {
1189 u8 nr_drv_agg_frames;
1190 struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
1191}__attribute__((packed));
1192
1193#define MAX_SUBFRAME_COUNT 64
1194struct ieee80211_rxb {
1195 u8 nr_subframes;
1196 struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
1197 u8 dst[ETH_ALEN];
1198 u8 src[ETH_ALEN];
1199}__attribute__((packed));
1200
1201typedef union _frameqos {
1202 u16 shortdata;
1203 u8 chardata[2];
1204 struct {
1205 u16 tid:4;
1206 u16 eosp:1;
1207 u16 ack_policy:2;
1208 u16 reserved:1;
1209 u16 txop:8;
1210 }field;
1211}frameqos,*pframeqos;
1212
1213/* SWEEP TABLE ENTRIES NUMBER*/
1214#define MAX_SWEEP_TAB_ENTRIES 42
1215#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
1216/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
1217 * only use 8, and then use extended rates for the remaining supported
1218 * rates. Other APs, however, stick all of their supported rates on the
1219 * main rates information element... */
1220#define MAX_RATES_LENGTH ((u8)12)
1221#define MAX_RATES_EX_LENGTH ((u8)16)
1222#define MAX_NETWORK_COUNT 128
1223
1224#define MAX_CHANNEL_NUMBER 161
1225#define IEEE80211_SOFTMAC_SCAN_TIME 100
1226//(HZ / 2)
1227#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
1228
1229#define CRC_LENGTH 4U
1230
1231#define MAX_WPA_IE_LEN 64
1232
1233#define NETWORK_EMPTY_ESSID (1<<0)
1234#define NETWORK_HAS_OFDM (1<<1)
1235#define NETWORK_HAS_CCK (1<<2)
1236
1237/* QoS structure */
1238#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
1239#define NETWORK_HAS_QOS_INFORMATION (1<<4)
1240#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \
1241 NETWORK_HAS_QOS_INFORMATION)
1242/* 802.11h */
1243#define NETWORK_HAS_POWER_CONSTRAINT (1<<5)
1244#define NETWORK_HAS_CSA (1<<6)
1245#define NETWORK_HAS_QUIET (1<<7)
1246#define NETWORK_HAS_IBSS_DFS (1<<8)
1247#define NETWORK_HAS_TPC_REPORT (1<<9)
1248
1249#define NETWORK_HAS_ERP_VALUE (1<<10)
1250
1251#define QOS_QUEUE_NUM 4
1252#define QOS_OUI_LEN 3
1253#define QOS_OUI_TYPE 2
1254#define QOS_ELEMENT_ID 221
1255#define QOS_OUI_INFO_SUB_TYPE 0
1256#define QOS_OUI_PARAM_SUB_TYPE 1
1257#define QOS_VERSION_1 1
1258#define QOS_AIFSN_MIN_VALUE 2
1259
1260struct ieee80211_qos_information_element {
1261 u8 elementID;
1262 u8 length;
1263 u8 qui[QOS_OUI_LEN];
1264 u8 qui_type;
1265 u8 qui_subtype;
1266 u8 version;
1267 u8 ac_info;
1268} __attribute__ ((packed));
1269
1270struct ieee80211_qos_ac_parameter {
1271 u8 aci_aifsn;
1272 u8 ecw_min_max;
1273 __le16 tx_op_limit;
1274} __attribute__ ((packed));
1275
1276struct ieee80211_qos_parameter_info {
1277 struct ieee80211_qos_information_element info_element;
1278 u8 reserved;
1279 struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
1280} __attribute__ ((packed));
1281
1282struct ieee80211_qos_parameters {
1283 __le16 cw_min[QOS_QUEUE_NUM];
1284 __le16 cw_max[QOS_QUEUE_NUM];
1285 u8 aifs[QOS_QUEUE_NUM];
1286 u8 flag[QOS_QUEUE_NUM];
1287 __le16 tx_op_limit[QOS_QUEUE_NUM];
1288} __attribute__ ((packed));
1289
1290struct ieee80211_qos_data {
1291 struct ieee80211_qos_parameters parameters;
1292 int active;
1293 int supported;
1294 u8 param_count;
1295 u8 old_param_count;
1296};
1297
1298struct ieee80211_tim_parameters {
1299 u8 tim_count;
1300 u8 tim_period;
1301} __attribute__ ((packed));
1302
1303//#else
1304struct ieee80211_wmm_ac_param {
1305 u8 ac_aci_acm_aifsn;
1306 u8 ac_ecwmin_ecwmax;
1307 u16 ac_txop_limit;
1308};
1309
1310struct ieee80211_wmm_ts_info {
1311 u8 ac_dir_tid;
1312 u8 ac_up_psb;
1313 u8 reserved;
1314} __attribute__ ((packed));
1315
1316struct ieee80211_wmm_tspec_elem {
1317 struct ieee80211_wmm_ts_info ts_info;
1318 u16 norm_msdu_size;
1319 u16 max_msdu_size;
1320 u32 min_serv_inter;
1321 u32 max_serv_inter;
1322 u32 inact_inter;
1323 u32 suspen_inter;
1324 u32 serv_start_time;
1325 u32 min_data_rate;
1326 u32 mean_data_rate;
1327 u32 peak_data_rate;
1328 u32 max_burst_size;
1329 u32 delay_bound;
1330 u32 min_phy_rate;
1331 u16 surp_band_allow;
1332 u16 medium_time;
1333}__attribute__((packed));
1334
1335enum eap_type {
1336 EAP_PACKET = 0,
1337 EAPOL_START,
1338 EAPOL_LOGOFF,
1339 EAPOL_KEY,
1340 EAPOL_ENCAP_ASF_ALERT
1341};
1342
1343static const char *eap_types[] = {
1344 [EAP_PACKET] = "EAP-Packet",
1345 [EAPOL_START] = "EAPOL-Start",
1346 [EAPOL_LOGOFF] = "EAPOL-Logoff",
1347 [EAPOL_KEY] = "EAPOL-Key",
1348 [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
1349};
1350
1351static inline const char *eap_get_type(int type)
1352{
1353 return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
1354}
1355//added by amy for reorder
1356static inline u8 Frame_QoSTID(u8* buf)
1357{
1358 struct ieee80211_hdr_3addr *hdr;
1359 u16 fc;
1360 hdr = (struct ieee80211_hdr_3addr *)buf;
1361 fc = le16_to_cpu(hdr->frame_ctl);
1362 return (u8)((frameqos*)(buf + (((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24)))->field.tid;
1363}
1364
1365//added by amy for reorder
1366
1367struct eapol {
1368 u8 snap[6];
1369 u16 ethertype;
1370 u8 version;
1371 u8 type;
1372 u16 length;
1373} __attribute__ ((packed));
1374
1375struct ieee80211_softmac_stats{
1376 unsigned int rx_ass_ok;
1377 unsigned int rx_ass_err;
1378 unsigned int rx_probe_rq;
1379 unsigned int tx_probe_rs;
1380 unsigned int tx_beacons;
1381 unsigned int rx_auth_rq;
1382 unsigned int rx_auth_rs_ok;
1383 unsigned int rx_auth_rs_err;
1384 unsigned int tx_auth_rq;
1385 unsigned int no_auth_rs;
1386 unsigned int no_ass_rs;
1387 unsigned int tx_ass_rq;
1388 unsigned int rx_ass_rq;
1389 unsigned int tx_probe_rq;
1390 unsigned int reassoc;
1391 unsigned int swtxstop;
1392 unsigned int swtxawake;
1393 unsigned char CurrentShowTxate;
1394 unsigned char last_packet_rate;
1395 unsigned int txretrycount;
1396};
1397
1398#define BEACON_PROBE_SSID_ID_POSITION 12
1399
1400struct ieee80211_info_element_hdr {
1401 u8 id;
1402 u8 len;
1403} __attribute__ ((packed));
1404
1405/*
1406 * These are the data types that can make up management packets
1407 *
1408 u16 auth_algorithm;
1409 u16 auth_sequence;
1410 u16 beacon_interval;
1411 u16 capability;
1412 u8 current_ap[ETH_ALEN];
1413 u16 listen_interval;
1414 struct {
1415 u16 association_id:14, reserved:2;
1416 } __attribute__ ((packed));
1417 u32 time_stamp[2];
1418 u16 reason;
1419 u16 status;
1420*/
1421
1422#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
1423#define IEEE80211_DEFAULT_BASIC_RATE 2 //1Mbps
1424
1425enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
1426#define MAX_SP_Len (WMM_all_frame << 4)
1427#define IEEE80211_QOS_TID 0x0f
1428#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
1429
1430#define IEEE80211_DTIM_MBCAST 4
1431#define IEEE80211_DTIM_UCAST 2
1432#define IEEE80211_DTIM_VALID 1
1433#define IEEE80211_DTIM_INVALID 0
1434
1435#define IEEE80211_PS_DISABLED 0
1436#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
1437#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
1438
1439//added by David for QoS 2006/6/30
1440//#define WMM_Hang_8187
1441#ifdef WMM_Hang_8187
1442#undef WMM_Hang_8187
1443#endif
1444
1445#define WME_AC_BK 0x00
1446#define WME_AC_BE 0x01
1447#define WME_AC_VI 0x02
1448#define WME_AC_VO 0x03
1449#define WME_ACI_MASK 0x03
1450#define WME_AIFSN_MASK 0x03
1451#define WME_AC_PRAM_LEN 16
1452
1453#define MAX_RECEIVE_BUFFER_SIZE 9100
1454
1455//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
1456#define UP2AC(up) ( \
1457 ((up) < 1) ? WME_AC_BE : \
1458 ((up) < 3) ? WME_AC_BK : \
1459 ((up) < 4) ? WME_AC_BE : \
1460 ((up) < 6) ? WME_AC_VI : \
1461 WME_AC_VO)
1462
1463//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
1464#define AC2UP(_ac) ( \
1465 ((_ac) == WME_AC_VO) ? 6 : \
1466 ((_ac) == WME_AC_VI) ? 5 : \
1467 ((_ac) == WME_AC_BK) ? 1 : \
1468 0)
1469
1470#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */
1471#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address plus ether type*/
1472
1473struct ether_header {
1474 u8 ether_dhost[ETHER_ADDR_LEN];
1475 u8 ether_shost[ETHER_ADDR_LEN];
1476 u16 ether_type;
1477} __attribute__((packed));
1478
1479#ifndef ETHERTYPE_PAE
1480#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */
1481#endif
1482#ifndef ETHERTYPE_IP
1483#define ETHERTYPE_IP 0x0800 /* IP protocol */
1484#endif
1485
1486typedef struct _bss_ht{
1487
1488 bool support_ht;
1489
1490 // HT related elements
1491 u8 ht_cap_buf[32];
1492 u16 ht_cap_len;
1493 u8 ht_info_buf[32];
1494 u16 ht_info_len;
1495
1496 HT_SPEC_VER ht_spec_ver;
1497
1498 bool aggregation;
1499 bool long_slot_time;
1500}bss_ht, *pbss_ht;
1501
1502typedef enum _erp_t{
1503 ERP_NonERPpresent = 0x01,
1504 ERP_UseProtection = 0x02,
1505 ERP_BarkerPreambleMode = 0x04,
1506} erp_t;
1507
1508
1509struct ieee80211_network {
1510 /* These entries are used to identify a unique network */
1511 u8 bssid[ETH_ALEN];
1512 u8 channel;
1513 /* Ensure null-terminated for any debug msgs */
1514 u8 ssid[IW_ESSID_MAX_SIZE + 1];
1515 u8 ssid_len;
1516 struct ieee80211_qos_data qos_data;
1517
1518 //added by amy for LEAP
1519 bool bWithAironetIE;
1520 bool bCkipSupported;
1521 bool bCcxRmEnable;
1522 u16 CcxRmState[2];
1523 // CCXv4 S59, MBSSID.
1524 bool bMBssidValid;
1525 u8 MBssidMask;
1526 u8 MBssid[6];
1527 // CCX 2 S38, WLAN Device Version Number element. Annie, 2006-08-20.
1528 bool bWithCcxVerNum;
1529 u8 BssCcxVerNumber;
1530 /* These are network statistics */
1531 struct ieee80211_rx_stats stats;
1532 u16 capability;
1533 u8 rates[MAX_RATES_LENGTH];
1534 u8 rates_len;
1535 u8 rates_ex[MAX_RATES_EX_LENGTH];
1536 u8 rates_ex_len;
1537 unsigned long last_scanned;
1538 u8 mode;
1539 u32 flags;
1540 u32 last_associate;
1541 u32 time_stamp[2];
1542 u16 beacon_interval;
1543 u16 listen_interval;
1544 u16 atim_window;
1545 u8 erp_value;
1546 u8 wpa_ie[MAX_WPA_IE_LEN];
1547 size_t wpa_ie_len;
1548 u8 rsn_ie[MAX_WPA_IE_LEN];
1549 size_t rsn_ie_len;
1550
1551 struct ieee80211_tim_parameters tim;
1552 u8 dtim_period;
1553 u8 dtim_data;
1554 u32 last_dtim_sta_time[2];
1555
1556 //appeded for QoS
1557 u8 wmm_info;
1558 struct ieee80211_wmm_ac_param wmm_param[4];
1559 u8 QoS_Enable;
1560#ifdef THOMAS_TURBO
1561 u8 Turbo_Enable;//enable turbo mode, added by thomas
1562#endif
1563#ifdef ENABLE_DOT11D
1564 u16 CountryIeLen;
1565 u8 CountryIeBuf[MAX_IE_LEN];
1566#endif
1567 // HT Related, by amy, 2008.04.29
1568 BSS_HT bssht;
1569 // Add to handle broadcom AP management frame CCK rate.
1570 bool broadcom_cap_exist;
1571 bool ralink_cap_exist;
1572 bool atheros_cap_exist;
1573 bool cisco_cap_exist;
1574 bool marvell_cap_exist;
1575 bool unknown_cap_exist;
1576// u8 berp_info;
1577 bool berp_info_valid;
1578 bool buseprotection;
1579 //put at the end of the structure.
1580 struct list_head list;
1581};
1582
1583enum ieee80211_state {
1584
1585 /* the card is not linked at all */
1586 IEEE80211_NOLINK = 0,
1587
1588 /* IEEE80211_ASSOCIATING* are for BSS client mode
1589 * the driver shall not perform RX filtering unless
1590 * the state is LINKED.
1591 * The driver shall just check for the state LINKED and
1592 * defaults to NOLINK for ALL the other states (including
1593 * LINKED_SCANNING)
1594 */
1595
1596 /* the association procedure will start (wq scheduling)*/
1597 IEEE80211_ASSOCIATING,
1598 IEEE80211_ASSOCIATING_RETRY,
1599
1600 /* the association procedure is sending AUTH request*/
1601 IEEE80211_ASSOCIATING_AUTHENTICATING,
1602
1603 /* the association procedure has successfully authentcated
1604 * and is sending association request
1605 */
1606 IEEE80211_ASSOCIATING_AUTHENTICATED,
1607
1608 /* the link is ok. the card associated to a BSS or linked
1609 * to a ibss cell or acting as an AP and creating the bss
1610 */
1611 IEEE80211_LINKED,
1612
1613 /* same as LINKED, but the driver shall apply RX filter
1614 * rules as we are in NO_LINK mode. As the card is still
1615 * logically linked, but it is doing a syncro site survey
1616 * then it will be back to LINKED state.
1617 */
1618 IEEE80211_LINKED_SCANNING,
1619
1620};
1621
1622#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
1623#define DEFAULT_FTS 2346
1624
1625#define CFG_IEEE80211_RESERVE_FCS (1<<0)
1626#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
1627#define CFG_IEEE80211_RTS (1<<2)
1628
1629#define IEEE80211_24GHZ_MIN_CHANNEL 1
1630#define IEEE80211_24GHZ_MAX_CHANNEL 14
1631#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
1632 IEEE80211_24GHZ_MIN_CHANNEL + 1)
1633
1634#define IEEE80211_52GHZ_MIN_CHANNEL 34
1635#define IEEE80211_52GHZ_MAX_CHANNEL 165
1636#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
1637 IEEE80211_52GHZ_MIN_CHANNEL + 1)
1638
1639typedef struct tx_pending_t{
1640 int frag;
1641 struct ieee80211_txb *txb;
1642}tx_pending_t;
1643
1644typedef struct _bandwidth_autoswitch
1645{
1646 long threshold_20Mhzto40Mhz;
1647 long threshold_40Mhzto20Mhz;
1648 bool bforced_tx20Mhz;
1649 bool bautoswitch_enable;
1650}bandwidth_autoswitch,*pbandwidth_autoswitch;
1651
1652
1653//added by amy for order
1654
1655#define REORDER_WIN_SIZE 128
1656#define REORDER_ENTRY_NUM 128
1657typedef struct _RX_REORDER_ENTRY
1658{
1659 struct list_head List;
1660 u16 SeqNum;
1661 struct ieee80211_rxb* prxb;
1662} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY;
1663//added by amy for order
1664typedef enum _Fsync_State{
1665 Default_Fsync,
1666 HW_Fsync,
1667 SW_Fsync
1668}Fsync_State;
1669
1670typedef struct _IbssParms{
1671 u16 atimWin;
1672}IbssParms, *PIbssParms;
1673#define MAX_NUM_RATES 264 // Max num of support rates element: 8, Max num of ext. support rate: 255. 061122, by rcnjko.
1674
1675#ifdef ENABLE_DOT11D
1676typedef enum
1677{
1678 COUNTRY_CODE_FCC = 0,
1679 COUNTRY_CODE_IC = 1,
1680 COUNTRY_CODE_ETSI = 2,
1681 COUNTRY_CODE_SPAIN = 3,
1682 COUNTRY_CODE_FRANCE = 4,
1683 COUNTRY_CODE_MKK = 5,
1684 COUNTRY_CODE_MKK1 = 6,
1685 COUNTRY_CODE_ISRAEL = 7,
1686 COUNTRY_CODE_TELEC,
1687 COUNTRY_CODE_MIC,
1688 COUNTRY_CODE_GLOBAL_DOMAIN
1689}country_code_type_t;
1690#endif
1691
1692#define RT_MAX_LD_SLOT_NUM 10
1693typedef struct _RT_LINK_DETECT_T{
1694
1695 u32 NumRecvBcnInPeriod;
1696 u32 NumRecvDataInPeriod;
1697
1698 u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; // number of Rx beacon / CheckForHang_period to determine link status
1699 u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; // number of Rx data / CheckForHang_period to determine link status
1700 u16 SlotNum; // number of CheckForHang period to determine link status
1701 u16 SlotIndex;
1702
1703 u32 NumTxOkInPeriod;
1704 u32 NumRxOkInPeriod;
1705 u32 NumRxUnicastOkInPeriod;
1706 bool bBusyTraffic;
1707}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
1708
1709//added by amy 090330
1710typedef enum _HW_VARIABLES{
1711 HW_VAR_ETHER_ADDR,
1712 HW_VAR_MULTICAST_REG,
1713 HW_VAR_BASIC_RATE,
1714 HW_VAR_BSSID,
1715 HW_VAR_MEDIA_STATUS,
1716 HW_VAR_SECURITY_CONF,
1717 HW_VAR_BEACON_INTERVAL,
1718 HW_VAR_ATIM_WINDOW,
1719 HW_VAR_LISTEN_INTERVAL,
1720 HW_VAR_CS_COUNTER,
1721 HW_VAR_DEFAULTKEY0,
1722 HW_VAR_DEFAULTKEY1,
1723 HW_VAR_DEFAULTKEY2,
1724 HW_VAR_DEFAULTKEY3,
1725 HW_VAR_SIFS,
1726 HW_VAR_DIFS,
1727 HW_VAR_EIFS,
1728 HW_VAR_SLOT_TIME,
1729 HW_VAR_ACK_PREAMBLE,
1730 HW_VAR_CW_CONFIG,
1731 HW_VAR_CW_VALUES,
1732 HW_VAR_RATE_FALLBACK_CONTROL,
1733 HW_VAR_CONTENTION_WINDOW,
1734 HW_VAR_RETRY_COUNT,
1735 HW_VAR_TR_SWITCH,
1736 HW_VAR_COMMAND, // For Command Register, Annie, 2006-04-07.
1737 HW_VAR_WPA_CONFIG, //2004/08/23, kcwu, for 8187 Security config
1738 HW_VAR_AMPDU_MIN_SPACE, // The spacing between sub-frame. Roger, 2008.07.04.
1739 HW_VAR_SHORTGI_DENSITY, // The density for shortGI. Roger, 2008.07.04.
1740 HW_VAR_AMPDU_FACTOR,
1741 HW_VAR_MCS_RATE_AVAILABLE,
1742 HW_VAR_AC_PARAM, // For AC Parameters, 2005.12.01, by rcnjko.
1743 HW_VAR_ACM_CTRL, // For ACM Control, Annie, 2005-12-13.
1744 HW_VAR_DIS_Req_Qsize, // For DIS_Reg_Qsize, Joseph
1745 HW_VAR_CCX_CHNL_LOAD, // For CCX 2 channel load request, 2006.05.04.
1746 HW_VAR_CCX_NOISE_HISTOGRAM, // For CCX 2 noise histogram request, 2006.05.04.
1747 HW_VAR_CCX_CLM_NHM, // For CCX 2 parallel channel load request and noise histogram request, 2006.05.12.
1748 HW_VAR_TxOPLimit, // For turbo mode related settings, added by Roger, 2006.12.07
1749 HW_VAR_TURBO_MODE, // For turbo mode related settings, added by Roger, 2006.12.15.
1750 HW_VAR_RF_STATE, // For change or query RF power state, 061214, rcnjko.
1751 HW_VAR_RF_OFF_BY_HW, // For UI to query if external HW signal disable RF, 061229, rcnjko.
1752 HW_VAR_BUS_SPEED, // In unit of bps. 2006.07.03, by rcnjko.
1753 HW_VAR_SET_DEV_POWER, // Set to low power, added by LanHsin, 2007.
1754
1755 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
1756 //1Attention Please!!!<11n or 8190 specific code should be put below this line>
1757 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
1758 HW_VAR_RCR, //for RCR, David 2006,05,11
1759 HW_VAR_RATR_0,
1760 HW_VAR_RRSR,
1761 HW_VAR_CPU_RST,
1762 HW_VAR_CHECK_BSSID,
1763 HW_VAR_LBK_MODE, // Set lookback mode, 2008.06.11. added by Roger.
1764 // Set HW related setting for 11N AES bug.
1765 HW_VAR_AES_11N_FIX,
1766 // Set Usb Rx Aggregation
1767 HW_VAR_USB_RX_AGGR,
1768 HW_VAR_USER_CONTROL_TURBO_MODE,
1769 HW_VAR_RETRY_LIMIT,
1770#ifndef _RTL8192_EXT_PATCH_
1771 HW_VAR_INIT_TX_RATE, //Get Current Tx rate register. 2008.12.10. Added by tynli
1772#endif
1773 HW_VAR_TX_RATE_REG, //Get Current Tx rate register. 2008.12.10. Added by tynli
1774 HW_VAR_EFUSE_USAGE, //Get current EFUSE utilization. 2008.12.19. Added by Roger.
1775 HW_VAR_EFUSE_BYTES,
1776 HW_VAR_AUTOLOAD_STATUS, //Get current autoload status, 0: autoload success, 1: autoload fail. 2008.12.19. Added by Roger.
1777 HW_VAR_RF_2R_DISABLE, // 2R disable
1778 HW_VAR_SET_RPWM,
1779 HW_VAR_H2C_FW_PWRMODE, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
1780 HW_VAR_H2C_FW_JOINBSSRPT, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
1781 HW_VAR_1X1_RECV_COMBINE, // For 1T2R but only 1SS, Add by hpfan 2009.04.16 hpfan
1782 HW_VAR_STOP_SEND_BEACON,
1783 HW_VAR_TSF_TIMER, // Read from TSF register to get the current TSF timer, by Bruce, 2009-07-22.
1784 HW_VAR_IO_CMD,
1785 HW_VAR_HANDLE_FW_C2H, //Added by tynli. For handling FW C2H command. 2009.10.07.
1786 HW_VAR_DL_FW_RSVD_PAGE, //Added by tynli. Download the packets that FW will use to RSVD page. 2009.10.14.
1787 HW_VAR_AID, //Added by tynli.
1788 HW_VAR_HW_SEQ_ENABLE, //Added by tynli. 2009.10.20.
1789 HW_VAR_UPDATE_TSF, //Added by tynli. 2009.10.22. For Hw count TBTT time.
1790 HW_VAR_BCN_VALID, //Added by tynli.
1791 HW_VAR_FWLPS_RF_ON //Added by tynli. 2009.11.09. For checking if Fw finishs RF on sequence.
1792}HW_VARIABLES;
1793
1794#define RT_CHECK_FOR_HANG_PERIOD 2
1795
1796struct ieee80211_device {
1797 struct net_device *dev;
1798 struct ieee80211_security sec;
1799
1800 bool need_sw_enc;
1801#ifdef ENABLE_LPS
1802 bool bAwakePktSent;
1803 u8 LPSDelayCnt;
1804 bool bIsAggregateFrame;
1805 bool polling;
1806 void (*LeisurePSLeave)(struct ieee80211_device *ieee);
1807#endif
1808
1809#ifdef ENABLE_IPS
1810 bool proto_stoppping;
1811 bool wx_set_enc;
1812 struct semaphore ips_sem;
1813 struct work_struct ips_leave_wq;
1814 void (*ieee80211_ips_leave_wq) (struct ieee80211_device *ieee);
1815 void (*ieee80211_ips_leave)(struct ieee80211_device *ieee);
1816#endif
1817 void (*SetHwRegHandler)(struct ieee80211_device *ieee, u8 variable, u8 *val);
1818 u8 (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
1819
1820 //hw security related
1821 u8 hwsec_active; //hw security active.
1822 bool is_silent_reset;
1823 bool is_roaming;
1824 bool ieee_up;
1825 bool bSupportRemoteWakeUp;
1826 bool actscanning;
1827 bool beinretry;
1828 bool is_set_key;
1829 //11n spec related I wonder if These info structure need to be moved out of ieee80211_device
1830
1831 //11n HT below
1832 PRT_HIGH_THROUGHPUT pHTInfo;
1833 spinlock_t bw_spinlock;
1834
1835 spinlock_t reorder_spinlock;
1836 // for HT operation rate set. we use this one for HT data rate to separate different descriptors
1837 //the way fill this is the same as in the IE
1838 u8 Regdot11HTOperationalRateSet[16]; //use RATR format
1839 u8 dot11HTOperationalRateSet[16]; //use RATR format
1840 u8 RegHTSuppRateSet[16];
1841 u8 HTCurrentOperaRate;
1842 u8 HTHighestOperaRate;
1843 //wb added for rate operation mode to firmware
1844 u8 bTxDisableRateFallBack;
1845 u8 bTxUseDriverAssingedRate;
1846 atomic_t atm_chnlop;
1847 atomic_t atm_swbw;
1848
1849 // 802.11e and WMM Traffic Stream Info (TX)
1850 struct list_head Tx_TS_Admit_List;
1851 struct list_head Tx_TS_Pending_List;
1852 struct list_head Tx_TS_Unused_List;
1853 TX_TS_RECORD TxTsRecord[TOTAL_TS_NUM];
1854 // 802.11e and WMM Traffic Stream Info (RX)
1855 struct list_head Rx_TS_Admit_List;
1856 struct list_head Rx_TS_Pending_List;
1857 struct list_head Rx_TS_Unused_List;
1858 RX_TS_RECORD RxTsRecord[TOTAL_TS_NUM];
1859 RX_REORDER_ENTRY RxReorderEntry[128];
1860 struct list_head RxReorder_Unused_List;
1861 u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.)
1862
1863
1864 /* Bookkeeping structures */
1865 struct net_device_stats stats;
1866 struct ieee80211_stats ieee_stats;
1867 struct ieee80211_softmac_stats softmac_stats;
1868
1869 /* Probe / Beacon management */
1870 struct list_head network_free_list;
1871 struct list_head network_list;
1872 struct ieee80211_network *networks;
1873 int scans;
1874 int scan_age;
1875
1876 int iw_mode; /* operating mode (IW_MODE_*) */
1877 struct iw_spy_data spy_data;
1878
1879 spinlock_t lock;
1880 spinlock_t wpax_suitlist_lock;
1881
1882 int tx_headroom; /* Set to size of any additional room needed at front
1883 * of allocated Tx SKBs */
1884 u32 config;
1885
1886 /* WEP and other encryption related settings at the device level */
1887 int open_wep; /* Set to 1 to allow unencrypted frames */
1888 int auth_mode;
1889 int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
1890 * WEP key changes */
1891
1892 /* If the host performs {en,de}cryption, then set to 1 */
1893 int host_encrypt;
1894 int host_encrypt_msdu;
1895 int host_decrypt;
1896 /* host performs multicast decryption */
1897 int host_mc_decrypt;
1898
1899 /* host should strip IV and ICV from protected frames */
1900 /* meaningful only when hardware decryption is being used */
1901 int host_strip_iv_icv;
1902
1903 int host_open_frag;
1904 int host_build_iv;
1905 int ieee802_1x; /* is IEEE 802.1X used */
1906
1907 /* WPA data */
1908 bool bHalfWirelessN24GMode;
1909 int wpa_enabled;
1910 int drop_unencrypted;
1911 int tkip_countermeasures;
1912 int privacy_invoked;
1913 size_t wpa_ie_len;
1914 u8 *wpa_ie;
1915 u8 ap_mac_addr[6];
1916 u16 pairwise_key_type;
1917 u16 group_key_type;
1918 struct list_head crypt_deinit_list;
1919 struct ieee80211_crypt_data *crypt[WEP_KEYS];
1920 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
1921 struct timer_list crypt_deinit_timer;
1922 int crypt_quiesced;
1923
1924 int bcrx_sta_key; /* use individual keys to override default keys even
1925 * with RX of broad/multicast frames */
1926
1927 /* Fragmentation structures */
1928 // each streaming contain a entry
1929 struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
1930 unsigned int frag_next_idx[17];
1931 u16 fts; /* Fragmentation Threshold */
1932#define DEFAULT_RTS_THRESHOLD 2346U
1933#define MIN_RTS_THRESHOLD 1
1934#define MAX_RTS_THRESHOLD 2346U
1935 u16 rts; /* RTS threshold */
1936
1937 /* Association info */
1938 u8 bssid[ETH_ALEN];
1939
1940 /* This stores infos for the current network.
1941 * Either the network we are associated in INFRASTRUCTURE
1942 * or the network that we are creating in MASTER mode.
1943 * ad-hoc is a mixture ;-).
1944 * Note that in infrastructure mode, even when not associated,
1945 * fields bssid and essid may be valid (if wpa_set and essid_set
1946 * are true) as thy carry the value set by the user via iwconfig
1947 */
1948 struct ieee80211_network current_network;
1949
1950 enum ieee80211_state state;
1951
1952 int short_slot;
1953 int reg_mode;
1954 int mode; /* A, B, G */
1955 int modulation; /* CCK, OFDM */
1956 int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */
1957 int abg_true; /* ABG flag */
1958
1959 /* used for forcing the ibss workqueue to terminate
1960 * without wait for the syncro scan to terminate
1961 */
1962 short sync_scan_hurryup;
1963
1964 int perfect_rssi;
1965 int worst_rssi;
1966
1967 u16 prev_seq_ctl; /* used to drop duplicate frames */
1968
1969 /* map of allowed channels. 0 is dummy */
1970 // FIXME: remember to default to a basic channel plan depending of the PHY type
1971#ifdef ENABLE_DOT11D
1972 void* pDot11dInfo;
1973 bool bGlobalDomain;
1974#else
1975 int channel_map[MAX_CHANNEL_NUMBER+1];
1976#endif
1977 int rate; /* current rate */
1978 int basic_rate;
1979 //FIXME: pleace callback, see if redundant with softmac_features
1980 short active_scan;
1981
1982 /* this contains flags for selectively enable softmac support */
1983 u16 softmac_features;
1984
1985 /* if the sequence control field is not filled by HW */
1986 u16 seq_ctrl[5];
1987
1988 /* association procedure transaction sequence number */
1989 u16 associate_seq;
1990
1991 /* AID for RTXed association responses */
1992 u16 assoc_id;
1993
1994 /* power save mode related*/
1995 u8 ack_tx_to_ieee;
1996 short ps;
1997 short sta_sleep;
1998 int ps_timeout;
1999 int ps_period;
2000 struct tasklet_struct ps_task;
2001 u32 ps_th;
2002 u32 ps_tl;
2003
2004 short raw_tx;
2005 /* used if IEEE_SOFTMAC_TX_QUEUE is set */
2006 short queue_stop;
2007 short scanning;
2008 short proto_started;
2009
2010 struct semaphore wx_sem;
2011 struct semaphore scan_sem;
2012
2013 spinlock_t mgmt_tx_lock;
2014 spinlock_t beacon_lock;
2015
2016 short beacon_txing;
2017
2018 short wap_set;
2019 short ssid_set;
2020
2021 u8 wpax_type_set; //{added by David, 2006.9.28}
2022 u32 wpax_type_notify; //{added by David, 2006.9.26}
2023
2024 /* QoS related flag */
2025 char init_wmmparam_flag;
2026 /* set on initialization */
2027 u8 qos_support;
2028
2029 /* for discarding duplicated packets in IBSS */
2030 struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
2031
2032 /* for discarding duplicated packets in BSS */
2033 u16 last_rxseq_num[17]; /* rx seq previous per-tid */
2034 u16 last_rxfrag_num[17];/* tx frag previous per-tid */
2035 unsigned long last_packet_time[17];
2036
2037 /* for PS mode */
2038 unsigned long last_rx_ps_time;
2039 u8 LPSAwakeIntvl;
2040 u8 RegMaxLPSAwakeIntvl;
2041
2042 /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
2043 struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
2044 int mgmt_queue_head;
2045 int mgmt_queue_tail;
2046#define IEEE80211_QUEUE_LIMIT 128
2047 u8 AsocRetryCount;
2048 unsigned int hw_header;
2049 struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE];
2050 struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE];
2051 struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE];
2052 u32 sta_edca_param[4];
2053 bool aggregation;
2054 // Enable/Disable Rx immediate BA capability.
2055 bool enable_rx_imm_BA;
2056 bool bibsscoordinator;
2057
2058 //+by amy for DM ,080515
2059 //Dynamic Tx power for near/far range enable/Disable , by amy , 2008-05-15
2060 bool bdynamic_txpower_enable;
2061
2062 bool bCTSToSelfEnable;
2063 u8 CTSToSelfTH;
2064
2065 u32 fsync_time_interval;
2066 u32 fsync_rate_bitmap;
2067 u8 fsync_rssi_threshold;
2068 bool bfsync_enable;
2069
2070 u8 fsync_multiple_timeinterval; // FsyncMultipleTimeInterval * FsyncTimeInterval
2071 u32 fsync_firstdiff_ratethreshold; // low threshold
2072 u32 fsync_seconddiff_ratethreshold; // decrease threshold
2073 Fsync_State fsync_state;
2074 bool bis_any_nonbepkts;
2075 //20Mhz 40Mhz AutoSwitch Threshold
2076 bandwidth_autoswitch bandwidth_auto_switch;
2077 //for txpower tracking
2078 bool FwRWRF;
2079
2080 //added by amy for AP roaming
2081 RT_LINK_DETECT_T LinkDetectInfo;
2082
2083 /* used if IEEE_SOFTMAC_TX_QUEUE is set */
2084 struct tx_pending_t tx_pending;
2085
2086 /* used if IEEE_SOFTMAC_ASSOCIATE is set */
2087 struct timer_list associate_timer;
2088
2089 /* used if IEEE_SOFTMAC_BEACONS is set */
2090 struct timer_list beacon_timer;
2091 struct work_struct associate_complete_wq;
2092 struct work_struct associate_procedure_wq;
2093 struct delayed_work softmac_scan_wq;
2094 struct delayed_work associate_retry_wq;
2095 struct delayed_work start_ibss_wq;
2096 struct delayed_work hw_wakeup_wq;
2097
2098 struct work_struct wx_sync_scan_wq;
2099 struct workqueue_struct *wq;
2100
2101 /* Callback functions */
2102 void (*set_security)(struct ieee80211_device *ieee,
2103 struct ieee80211_security *sec);
2104
2105 /* Used to TX data frame by using txb structs.
2106 * this is not used if in the softmac_features
2107 * is set the flag IEEE_SOFTMAC_TX_QUEUE
2108 */
2109 int (*hard_start_xmit)(struct ieee80211_txb *txb,
2110 struct ieee80211_device *ieee);
2111
2112 int (*reset_port)(struct ieee80211_device *ieee);
2113 int (*is_queue_full) (struct ieee80211_device *ieee, int pri);
2114
2115 int (*handle_management) (struct ieee80211_device *ieee,
2116 struct ieee80211_network * network, u16 type);
2117 int (*is_qos_active) (struct ieee80211_device *ieee, struct sk_buff *skb);
2118
2119 /* Softmac-generated frames (mamagement) are TXed via this
2120 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
2121 * not set. As some cards may have different HW queues that
2122 * one might want to use for data and management frames
2123 * the option to have two callbacks might be useful.
2124 * This function can't sleep.
2125 */
2126 int (*softmac_hard_start_xmit)(struct sk_buff *skb,
2127 struct ieee80211_device *ieee80211);
2128
2129 /* used instead of hard_start_xmit (not softmac_hard_start_xmit)
2130 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
2131 * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
2132 * then also management frames are sent via this callback.
2133 * This function can't sleep.
2134 */
2135 void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
2136 struct ieee80211_device *ieee80211, int rate);
2137
2138 /* stops the HW queue for DATA frames. Useful to avoid
2139 * waste time to TX data frame when we are reassociating
2140 * This function can sleep.
2141 */
2142 void (*data_hard_stop)(struct ieee80211_device *ieee80211);
2143
2144 /* OK this is complementar to data_poll_hard_stop */
2145 void (*data_hard_resume)(struct ieee80211_device *ieee80211);
2146
2147 /* ask to the driver to retune the radio .
2148 * This function can sleep. the driver should ensure
2149 * the radio has been swithced before return.
2150 */
2151 void (*set_chan)(struct ieee80211_device *ieee80211, short ch);
2152
2153 /* These are not used if the ieee stack takes care of
2154 * scanning (IEEE_SOFTMAC_SCAN feature set).
2155 * In this case only the set_chan is used.
2156 *
2157 * The syncro version is similar to the start_scan but
2158 * does not return until all channels has been scanned.
2159 * this is called in user context and should sleep,
2160 * it is called in a work_queue when swithcing to ad-hoc mode
2161 * or in behalf of iwlist scan when the card is associated
2162 * and root user ask for a scan.
2163 * the function stop_scan should stop both the syncro and
2164 * background scanning and can sleep.
2165 * The function start_scan should initiate the background
2166 * scanning and can't sleep.
2167 */
2168 void (*scan_syncro)(struct ieee80211_device *ieee80211);
2169 void (*start_scan)(struct ieee80211_device *ieee80211);
2170 void (*stop_scan)(struct ieee80211_device *ieee80211);
2171
2172 /* indicate the driver that the link state is changed
2173 * for example it may indicate the card is associated now.
2174 * Driver might be interested in this to apply RX filter
2175 * rules or simply light the LINK led
2176 */
2177 void (*link_change)(struct ieee80211_device *ieee80211);
2178
2179 /* these two function indicates to the HW when to start
2180 * and stop to send beacons. This is used when the
2181 * IEEE_SOFTMAC_BEACONS is not set. For now the
2182 * stop_send_bacons is NOT guaranteed to be called only
2183 * after start_send_beacons.
2184 */
2185 void (*start_send_beacons) (struct ieee80211_device *dev);
2186 void (*stop_send_beacons) (struct ieee80211_device *dev);
2187
2188 /* power save mode related */
2189 void (*sta_wake_up) (struct ieee80211_device *ieee80211);
2190 void (*enter_sleep_state) (struct ieee80211_device *ieee80211, u32 th, u32 tl);
2191 short (*ps_is_queue_empty) (struct ieee80211_device *ieee80211);
2192 int (*handle_beacon) (struct ieee80211_device *ieee80211, struct ieee80211_beacon *beacon, struct ieee80211_network *network);
2193 int (*handle_assoc_response) (struct ieee80211_device *ieee80211, struct ieee80211_assoc_response_frame *resp, struct ieee80211_network *network);
2194
2195 /* check whether Tx hw resouce available */
2196 short (*check_nic_enough_desc)(struct ieee80211_device *ieee80211, int queue_index);
2197 //added by wb for HT related
2198 void (*SetBWModeHandler)(struct ieee80211_device *ieee80211, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
2199 bool (*GetNmodeSupportBySecCfg)(struct ieee80211_device *ieee80211);
2200 void (*SetWirelessMode)(struct ieee80211_device *ieee80211, u8 wireless_mode);
2201 bool (*GetHalfNmodeSupportByAPsHandler)(struct ieee80211_device *ieee80211);
2202 void (*InitialGainHandler)(struct ieee80211_device *ieee80211, u8 Operation);
2203
2204 /* This must be the last item so that it points to the data
2205 * allocated beyond this structure by alloc_ieee80211 */
2206 u8 priv[0];
2207};
2208
2209#define RT_RF_OFF_LEVL_ASPM BIT0 // PCI ASPM
2210#define RT_RF_OFF_LEVL_CLK_REQ BIT1 // PCI clock request
2211#define RT_RF_OFF_LEVL_PCI_D3 BIT2 // PCI D3 mode
2212#define RT_RF_OFF_LEVL_HALT_NIC BIT3 // NIC halt, re-initialize hw parameters
2213#define RT_RF_OFF_LEVL_FREE_FW BIT4 // FW free, re-download the FW
2214#define RT_RF_OFF_LEVL_FW_32K BIT5 // FW in 32k
2215#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6 // Always enable ASPM and Clock Req in initialization.
2216#define RT_RF_LPS_DISALBE_2R BIT30 // When LPS is on, disable 2R if no packet is received or transmittd.
2217#define RT_RF_LPS_LEVEL_ASPM BIT31 // LPS with ASPM
2218#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
2219#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel &= (~(_PS_FLAG)))
2220#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG)
2221
2222#define IEEE_A (1<<0)
2223#define IEEE_B (1<<1)
2224#define IEEE_G (1<<2)
2225#define IEEE_N_24G (1<<4)
2226#define IEEE_N_5G (1<<5)
2227#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
2228
2229/* Generate a 802.11 header */
2230
2231/* Uses the channel change callback directly
2232 * instead of [start/stop] scan callbacks
2233 */
2234#define IEEE_SOFTMAC_SCAN (1<<2)
2235
2236/* Perform authentication and association handshake */
2237#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
2238
2239/* Generate probe requests */
2240#define IEEE_SOFTMAC_PROBERQ (1<<4)
2241
2242/* Generate respones to probe requests */
2243#define IEEE_SOFTMAC_PROBERS (1<<5)
2244
2245/* The ieee802.11 stack will manages the netif queue
2246 * wake/stop for the driver, taking care of 802.11
2247 * fragmentation. See softmac.c for details. */
2248#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
2249
2250/* Uses only the softmac_data_hard_start_xmit
2251 * even for TX management frames.
2252 */
2253#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
2254
2255/* Generate beacons. The stack will enqueue beacons
2256 * to the card
2257 */
2258#define IEEE_SOFTMAC_BEACONS (1<<6)
2259
2260static inline void *ieee80211_priv(struct net_device *dev)
2261{
2262 return ((struct ieee80211_device *)netdev_priv(dev))->priv;
2263}
2264
2265extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
2266{
2267 /* Single white space is for Linksys APs */
2268 if (essid_len == 1 && essid[0] == ' ')
2269 return 1;
2270
2271 /* Otherwise, if the entire essid is 0, we assume it is hidden */
2272 while (essid_len) {
2273 essid_len--;
2274 if (essid[essid_len] != '\0')
2275 return 0;
2276 }
2277
2278 return 1;
2279}
2280
2281extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
2282{
2283 /*
2284 * It is possible for both access points and our device to support
2285 * combinations of modes, so as long as there is one valid combination
2286 * of ap/device supported modes, then return success
2287 *
2288 */
2289 if ((mode & IEEE_A) &&
2290 (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
2291 (ieee->freq_band & IEEE80211_52GHZ_BAND))
2292 return 1;
2293
2294 if ((mode & IEEE_G) &&
2295 (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
2296 (ieee->freq_band & IEEE80211_24GHZ_BAND))
2297 return 1;
2298
2299 if ((mode & IEEE_B) &&
2300 (ieee->modulation & IEEE80211_CCK_MODULATION) &&
2301 (ieee->freq_band & IEEE80211_24GHZ_BAND))
2302 return 1;
2303
2304 return 0;
2305}
2306
2307extern inline int ieee80211_get_hdrlen(u16 fc)
2308{
2309 int hdrlen = IEEE80211_3ADDR_LEN;
2310
2311 switch (WLAN_FC_GET_TYPE(fc)) {
2312 case IEEE80211_FTYPE_DATA:
2313 if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
2314 hdrlen = IEEE80211_4ADDR_LEN; /* Addr4 */
2315 if(IEEE80211_QOS_HAS_SEQ(fc))
2316 hdrlen += 2; /* QOS ctrl*/
2317 break;
2318 case IEEE80211_FTYPE_CTL:
2319 switch (WLAN_FC_GET_STYPE(fc)) {
2320 case IEEE80211_STYPE_CTS:
2321 case IEEE80211_STYPE_ACK:
2322 hdrlen = IEEE80211_1ADDR_LEN;
2323 break;
2324 default:
2325 hdrlen = IEEE80211_2ADDR_LEN;
2326 break;
2327 }
2328 break;
2329 }
2330
2331 return hdrlen;
2332}
2333
2334static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
2335{
2336 switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
2337 case IEEE80211_1ADDR_LEN:
2338 return ((struct ieee80211_hdr_1addr *)hdr)->payload;
2339 case IEEE80211_2ADDR_LEN:
2340 return ((struct ieee80211_hdr_2addr *)hdr)->payload;
2341 case IEEE80211_3ADDR_LEN:
2342 return ((struct ieee80211_hdr_3addr *)hdr)->payload;
2343 case IEEE80211_4ADDR_LEN:
2344 return ((struct ieee80211_hdr_4addr *)hdr)->payload;
2345 }
2346 return NULL;
2347}
2348
2349static inline int ieee80211_is_ofdm_rate(u8 rate)
2350{
2351 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
2352 case IEEE80211_OFDM_RATE_6MB:
2353 case IEEE80211_OFDM_RATE_9MB:
2354 case IEEE80211_OFDM_RATE_12MB:
2355 case IEEE80211_OFDM_RATE_18MB:
2356 case IEEE80211_OFDM_RATE_24MB:
2357 case IEEE80211_OFDM_RATE_36MB:
2358 case IEEE80211_OFDM_RATE_48MB:
2359 case IEEE80211_OFDM_RATE_54MB:
2360 return 1;
2361 }
2362 return 0;
2363}
2364
2365static inline int ieee80211_is_cck_rate(u8 rate)
2366{
2367 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
2368 case IEEE80211_CCK_RATE_1MB:
2369 case IEEE80211_CCK_RATE_2MB:
2370 case IEEE80211_CCK_RATE_5MB:
2371 case IEEE80211_CCK_RATE_11MB:
2372 return 1;
2373 }
2374 return 0;
2375}
2376
2377
2378/* ieee80211.c */
2379void free_ieee80211(struct net_device *dev);
2380struct net_device *alloc_ieee80211(int sizeof_priv);
2381
2382int ieee80211_set_encryption(struct ieee80211_device *ieee);
2383
2384/* ieee80211_tx.c */
2385
2386int ieee80211_encrypt_fragment(
2387 struct ieee80211_device *ieee,
2388 struct sk_buff *frag,
2389 int hdr_len);
2390
2391int ieee80211_rtl_xmit(struct sk_buff *skb,
2392 struct net_device *dev);
2393void ieee80211_txb_free(struct ieee80211_txb *);
2394
2395
2396/* ieee80211_rx.c */
2397int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
2398 struct ieee80211_rx_stats *rx_stats);
2399void ieee80211_rx_mgt(struct ieee80211_device *ieee,
2400 struct ieee80211_hdr_4addr *header,
2401 struct ieee80211_rx_stats *stats);
2402
2403/* ieee80211_wx.c */
2404int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
2405 struct iw_request_info *info,
2406 union iwreq_data *wrqu, char *key);
2407int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
2408 struct iw_request_info *info,
2409 union iwreq_data *wrqu, char *key);
2410int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
2411 struct iw_request_info *info,
2412 union iwreq_data *wrqu, char *key);
2413int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
2414 struct iw_request_info *info,
2415 union iwreq_data* wrqu, char *extra);
2416int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
2417 struct iw_request_info *info,
2418 union iwreq_data* wrqu, char *extra);
2419int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
2420 struct iw_request_info *info,
2421 struct iw_param *data, char *extra);
2422int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
2423 struct iw_request_info *info,
2424 union iwreq_data *wrqu, char *extra);
2425int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
2426
2427/* ieee80211_softmac.c */
2428short ieee80211_is_54g(struct ieee80211_network net);
2429short ieee80211_is_shortslot(struct ieee80211_network net);
2430int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2431 struct ieee80211_rx_stats *rx_stats, u16 type,
2432 u16 stype);
2433void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
2434
2435void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn);
2436void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
2437
2438void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
2439void notify_wx_assoc_event(struct ieee80211_device *ieee);
2440void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
2441void ieee80211_start_bss(struct ieee80211_device *ieee);
2442void ieee80211_start_master_bss(struct ieee80211_device *ieee);
2443void ieee80211_start_ibss(struct ieee80211_device *ieee);
2444void ieee80211_softmac_init(struct ieee80211_device *ieee);
2445void ieee80211_softmac_free(struct ieee80211_device *ieee);
2446void ieee80211_associate_abort(struct ieee80211_device *ieee);
2447void ieee80211_disassociate(struct ieee80211_device *ieee);
2448void ieee80211_stop_scan(struct ieee80211_device *ieee);
2449void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
2450void ieee80211_check_all_nets(struct ieee80211_device *ieee);
2451void ieee80211_start_protocol(struct ieee80211_device *ieee);
2452void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
2453void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
2454void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
2455void ieee80211_reset_queue(struct ieee80211_device *ieee);
2456void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
2457void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
2458struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
2459void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
2460void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
2461int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
2462void notify_wx_assoc_event(struct ieee80211_device *ieee);
2463void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
2464
2465void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
2466
2467/* ieee80211_crypt_ccmp&tkip&wep.c */
2468void ieee80211_tkip_null(void);
2469void ieee80211_wep_null(void);
2470void ieee80211_ccmp_null(void);
2471
2472/* ieee80211_softmac_wx.c */
2473
2474int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
2475 struct iw_request_info *info,
2476 union iwreq_data *wrqu, char *ext);
2477
2478int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
2479 struct iw_request_info *info,
2480 union iwreq_data *awrq,
2481 char *extra);
2482
2483int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
2484
2485int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
2486 struct iw_request_info *info,
2487 union iwreq_data *wrqu, char *extra);
2488
2489int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
2490 struct iw_request_info *info,
2491 union iwreq_data *wrqu, char *extra);
2492
2493int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
2494 union iwreq_data *wrqu, char *b);
2495
2496int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
2497 union iwreq_data *wrqu, char *b);
2498
2499int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
2500 struct iw_request_info *a,
2501 union iwreq_data *wrqu, char *extra);
2502
2503int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
2504 union iwreq_data *wrqu, char *b);
2505
2506int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
2507 union iwreq_data *wrqu, char *b);
2508
2509int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
2510 union iwreq_data *wrqu, char *b);
2511
2512void ieee80211_wx_sync_scan_wq(struct work_struct *work);
2513
2514int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
2515 struct iw_request_info *info,
2516 union iwreq_data *wrqu, char *extra);
2517
2518int ieee80211_wx_get_name(struct ieee80211_device *ieee,
2519 struct iw_request_info *info,
2520 union iwreq_data *wrqu, char *extra);
2521
2522int ieee80211_wx_set_power(struct ieee80211_device *ieee,
2523 struct iw_request_info *info,
2524 union iwreq_data *wrqu, char *extra);
2525
2526int ieee80211_wx_get_power(struct ieee80211_device *ieee,
2527 struct iw_request_info *info,
2528 union iwreq_data *wrqu, char *extra);
2529
2530int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
2531 struct iw_request_info *info,
2532 union iwreq_data *wrqu, char *extra);
2533
2534int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
2535 struct iw_request_info *info,
2536 union iwreq_data *wrqu, char *extra);
2537//HT
2538#define MAX_RECEIVE_BUFFER_SIZE 9100
2539void HTDebugHTCapability(u8 *CapIE, u8 *TitleString );
2540void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
2541
2542void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
2543void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
2544void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 isEncrypt);
2545void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 isEncrypt);
2546void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len);
2547void HTOnAssocRsp(struct ieee80211_device *ieee);
2548void HTInitializeHTInfo(struct ieee80211_device *ieee);
2549void HTInitializeBssDesc(PBSS_HT pBssHT);
2550void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
2551void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
2552u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter);
2553extern u8 MCS_FILTER_ALL[];
2554extern u16 MCS_DATA_RATE[2][2][77] ;
2555
2556u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
2557void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
2558bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
2559u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
2560u16 HTMcsToDataRate( struct ieee80211_device *ieee, u8 nMcsRate);
2561u16 TxCountToDataRate( struct ieee80211_device *ieee, u8 nDataRate);
2562int ieee80211_rx_ADDBAReq( struct ieee80211_device *ieee, struct sk_buff *skb);
2563int ieee80211_rx_ADDBARsp( struct ieee80211_device *ieee, struct sk_buff *skb);
2564int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb);
2565void TsInitAddBA( struct ieee80211_device *ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending);
2566void TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
2567void BaSetupTimeOut(unsigned long data);
2568void TxBaInactTimeout(unsigned long data);
2569void RxBaInactTimeout(unsigned long data);
2570void ResetBaEntry( PBA_RECORD pBA);
2571//function in TS.c
2572bool GetTs(
2573 struct ieee80211_device* ieee,
2574 PTS_COMMON_INFO *ppTS,
2575 u8* Addr,
2576 u8 TID,
2577 TR_SELECT TxRxSelect, //Rx:1, Tx:0
2578 bool bAddNewTs
2579 );
2580void TSInitialize(struct ieee80211_device *ieee);
2581void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS);
2582void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
2583void RemoveAllTS(struct ieee80211_device *ieee);
2584void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
2585
2586extern const long ieee80211_wlan_frequencies[];
2587
2588extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
2589{
2590 ieee->scans++;
2591}
2592
2593extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
2594{
2595 return ieee->scans;
2596}
2597
2598static inline const char *escape_essid(const char *essid, u8 essid_len) {
2599 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
2600 const char *s = essid;
2601 char *d = escaped;
2602
2603 if (ieee80211_is_empty_essid(essid, essid_len)) {
2604 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
2605 return escaped;
2606 }
2607
2608 essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
2609 while (essid_len--) {
2610 if (*s == '\0') {
2611 *d++ = '\\';
2612 *d++ = '0';
2613 s++;
2614 } else {
2615 *d++ = *s++;
2616 }
2617 }
2618 *d = '\0';
2619 return escaped;
2620}
2621
2622/* For the function is more related to hardware setting, it's better to use the
2623 * ieee handler to refer to it.
2624 */
2625int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
2626int ieee80211_parse_info_param(struct ieee80211_device *ieee,
2627 struct ieee80211_info_element *info_element,
2628 u16 length,
2629 struct ieee80211_network *network,
2630 struct ieee80211_rx_stats *stats);
2631
2632void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index);
2633void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr);
2634void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee);
2635#define RT_ASOC_RETRY_LIMIT 5
2636#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
new file mode 100644
index 00000000000..61fd4ced452
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -0,0 +1,244 @@
1/*
2 * Host AP crypto routines
3 *
4 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. See README and COPYING for
10 * more details.
11 *
12 */
13
14//#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <asm/string.h>
19#include <asm/errno.h>
20
21#include "ieee80211.h"
22
23//MODULE_AUTHOR("Jouni Malinen");
24//MODULE_DESCRIPTION("HostAP crypto");
25//MODULE_LICENSE("GPL");
26
27struct ieee80211_crypto_alg {
28 struct list_head list;
29 struct ieee80211_crypto_ops *ops;
30};
31
32
33struct ieee80211_crypto {
34 struct list_head algs;
35 spinlock_t lock;
36};
37
38static struct ieee80211_crypto *hcrypt;
39
40void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
41 int force)
42{
43 struct list_head *ptr, *n;
44 struct ieee80211_crypt_data *entry;
45
46 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
47 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
48 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
49
50 if (atomic_read(&entry->refcnt) != 0 && !force)
51 continue;
52
53 list_del(ptr);
54
55 if (entry->ops)
56 entry->ops->deinit(entry->priv);
57 kfree(entry);
58 }
59}
60
61void ieee80211_crypt_deinit_handler(unsigned long data)
62{
63 struct ieee80211_device *ieee = (struct ieee80211_device *)data;
64 unsigned long flags;
65
66 spin_lock_irqsave(&ieee->lock, flags);
67 ieee80211_crypt_deinit_entries(ieee, 0);
68 if (!list_empty(&ieee->crypt_deinit_list)) {
69 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
70 "deletion list\n", ieee->dev->name);
71 ieee->crypt_deinit_timer.expires = jiffies + HZ;
72 add_timer(&ieee->crypt_deinit_timer);
73 }
74 spin_unlock_irqrestore(&ieee->lock, flags);
75
76}
77
78void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
79 struct ieee80211_crypt_data **crypt)
80{
81 struct ieee80211_crypt_data *tmp;
82 unsigned long flags;
83
84 if (*crypt == NULL)
85 return;
86
87 tmp = *crypt;
88 *crypt = NULL;
89
90 /* must not run ops->deinit() while there may be pending encrypt or
91 * decrypt operations. Use a list of delayed deinits to avoid needing
92 * locking. */
93
94 spin_lock_irqsave(&ieee->lock, flags);
95 list_add(&tmp->list, &ieee->crypt_deinit_list);
96 if (!timer_pending(&ieee->crypt_deinit_timer)) {
97 ieee->crypt_deinit_timer.expires = jiffies + HZ;
98 add_timer(&ieee->crypt_deinit_timer);
99 }
100 spin_unlock_irqrestore(&ieee->lock, flags);
101}
102
103int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
104{
105 unsigned long flags;
106 struct ieee80211_crypto_alg *alg;
107
108 if (hcrypt == NULL)
109 return -1;
110
111 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
112 if (alg == NULL)
113 return -ENOMEM;
114
115 alg->ops = ops;
116
117 spin_lock_irqsave(&hcrypt->lock, flags);
118 list_add(&alg->list, &hcrypt->algs);
119 spin_unlock_irqrestore(&hcrypt->lock, flags);
120
121 printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
122 ops->name);
123
124 return 0;
125}
126
127int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
128{
129 unsigned long flags;
130 struct list_head *ptr;
131 struct ieee80211_crypto_alg *del_alg = NULL;
132
133 if (hcrypt == NULL)
134 return -1;
135
136 spin_lock_irqsave(&hcrypt->lock, flags);
137 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
138 struct ieee80211_crypto_alg *alg =
139 (struct ieee80211_crypto_alg *) ptr;
140 if (alg->ops == ops) {
141 list_del(&alg->list);
142 del_alg = alg;
143 break;
144 }
145 }
146 spin_unlock_irqrestore(&hcrypt->lock, flags);
147
148 if (del_alg) {
149 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
150 "'%s'\n", ops->name);
151 kfree(del_alg);
152 }
153
154 return del_alg ? 0 : -1;
155}
156
157
158struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
159{
160 unsigned long flags;
161 struct list_head *ptr;
162 struct ieee80211_crypto_alg *found_alg = NULL;
163
164 if (hcrypt == NULL)
165 return NULL;
166
167 spin_lock_irqsave(&hcrypt->lock, flags);
168 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
169 struct ieee80211_crypto_alg *alg =
170 (struct ieee80211_crypto_alg *) ptr;
171 if (strcmp(alg->ops->name, name) == 0) {
172 found_alg = alg;
173 break;
174 }
175 }
176 spin_unlock_irqrestore(&hcrypt->lock, flags);
177
178 if (found_alg)
179 return found_alg->ops;
180 else
181 return NULL;
182}
183
184
185static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
186static void ieee80211_crypt_null_deinit(void *priv) {}
187
188static struct ieee80211_crypto_ops ieee80211_crypt_null = {
189 .name = "NULL",
190 .init = ieee80211_crypt_null_init,
191 .deinit = ieee80211_crypt_null_deinit,
192 .encrypt_mpdu = NULL,
193 .decrypt_mpdu = NULL,
194 .encrypt_msdu = NULL,
195 .decrypt_msdu = NULL,
196 .set_key = NULL,
197 .get_key = NULL,
198 .extra_prefix_len = 0,
199 .extra_postfix_len = 0,
200 .owner = THIS_MODULE,
201};
202
203
204int __init ieee80211_crypto_init(void)
205{
206 int ret = -ENOMEM;
207
208 hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
209 if (!hcrypt)
210 goto out;
211
212 INIT_LIST_HEAD(&hcrypt->algs);
213 spin_lock_init(&hcrypt->lock);
214
215 ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
216 if (ret < 0) {
217 kfree(hcrypt);
218 hcrypt = NULL;
219 }
220out:
221 return ret;
222}
223
224
225void ieee80211_crypto_deinit(void)
226{
227 struct list_head *ptr, *n;
228
229 if (hcrypt == NULL)
230 return;
231
232 for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
233 ptr = n, n = ptr->next) {
234 struct ieee80211_crypto_alg *alg =
235 (struct ieee80211_crypto_alg *) ptr;
236 list_del(ptr);
237 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
238 "'%s' (deinit)\n", alg->ops->name);
239 kfree(alg);
240 }
241
242 kfree(hcrypt);
243}
244
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h
new file mode 100644
index 00000000000..ca7dd0dda82
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h
@@ -0,0 +1,85 @@
1/*
2 * Original code based on Host AP (software wireless LAN access point) driver
3 * for Intersil Prism2/2.5/3.
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 *
9 * Adaption to a generic IEEE 802.11 stack by James Ketrenos
10 * <jketreno@linux.intel.com>
11 *
12 * Copyright (c) 2004, Intel Corporation
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation. See README and COPYING for
17 * more details.
18 */
19
20/*
21 * This file defines the interface to the ieee80211 crypto module.
22 */
23#ifndef IEEE80211_CRYPT_H
24#define IEEE80211_CRYPT_H
25
26#include <linux/skbuff.h>
27
28struct ieee80211_crypto_ops {
29 const char *name;
30
31 /* init new crypto context (e.g., allocate private data space,
32 * select IV, etc.); returns NULL on failure or pointer to allocated
33 * private data on success */
34 void * (*init)(int keyidx);
35
36 /* deinitialize crypto context and free allocated private data */
37 void (*deinit)(void *priv);
38
39 /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
40 * value from decrypt_mpdu is passed as the keyidx value for
41 * decrypt_msdu. skb must have enough head and tail room for the
42 * encryption; if not, error will be returned; these functions are
43 * called for all MPDUs (i.e., fragments).
44 */
45 int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
46 int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
47
48 /* These functions are called for full MSDUs, i.e. full frames.
49 * These can be NULL if full MSDU operations are not needed. */
50 int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
51 int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
52 void *priv);
53
54 int (*set_key)(void *key, int len, u8 *seq, void *priv);
55 int (*get_key)(void *key, int len, u8 *seq, void *priv);
56
57 /* procfs handler for printing out key information and possible
58 * statistics */
59 char * (*print_stats)(char *p, void *priv);
60
61 /* maximum number of bytes added by encryption; encrypt buf is
62 * allocated with extra_prefix_len bytes, copy of in_buf, and
63 * extra_postfix_len; encrypt need not use all this space, but
64 * the result must start at the beginning of the buffer and correct
65 * length must be returned */
66 int extra_prefix_len, extra_postfix_len;
67
68 struct module *owner;
69};
70
71struct ieee80211_crypt_data {
72 struct list_head list; /* delayed deletion list */
73 struct ieee80211_crypto_ops *ops;
74 void *priv;
75 atomic_t refcnt;
76};
77
78int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
79int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
80struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
81void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
82void ieee80211_crypt_deinit_handler(unsigned long);
83void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
84 struct ieee80211_crypt_data **crypt);
85#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
new file mode 100644
index 00000000000..48267a058d1
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -0,0 +1,483 @@
1/*
2 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12//#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19#include <linux/if_ether.h>
20#include <linux/if_arp.h>
21#include <asm/string.h>
22#include <linux/wireless.h>
23
24#include "ieee80211.h"
25
26#include <linux/crypto.h>
27
28 #include <linux/scatterlist.h>
29
30MODULE_AUTHOR("Jouni Malinen");
31MODULE_DESCRIPTION("Host AP crypt: CCMP");
32MODULE_LICENSE("GPL");
33
34#ifndef OPENSUSE_SLED
35#define OPENSUSE_SLED 0
36#endif
37
38#define AES_BLOCK_LEN 16
39#define CCMP_HDR_LEN 8
40#define CCMP_MIC_LEN 8
41#define CCMP_TK_LEN 16
42#define CCMP_PN_LEN 6
43
44struct ieee80211_ccmp_data {
45 u8 key[CCMP_TK_LEN];
46 int key_set;
47
48 u8 tx_pn[CCMP_PN_LEN];
49 u8 rx_pn[CCMP_PN_LEN];
50
51 u32 dot11RSNAStatsCCMPFormatErrors;
52 u32 dot11RSNAStatsCCMPReplays;
53 u32 dot11RSNAStatsCCMPDecryptErrors;
54
55 int key_idx;
56
57 struct crypto_tfm *tfm;
58
59 /* scratch buffers for virt_to_page() (crypto API) */
60 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
61 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
62 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
63};
64
65void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
66 const u8 pt[16], u8 ct[16])
67{
68 crypto_cipher_encrypt_one((void*)tfm, ct, pt);
69}
70
71static void * ieee80211_ccmp_init(int key_idx)
72{
73 struct ieee80211_ccmp_data *priv;
74
75 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
76 if (priv == NULL)
77 goto fail;
78 priv->key_idx = key_idx;
79
80 priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
81 if (IS_ERR(priv->tfm)) {
82 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
83 "crypto API aes\n");
84 priv->tfm = NULL;
85 goto fail;
86 }
87 return priv;
88
89fail:
90 if (priv) {
91 if (priv->tfm)
92 crypto_free_cipher((void*)priv->tfm);
93 kfree(priv);
94 }
95
96 return NULL;
97}
98
99
100static void ieee80211_ccmp_deinit(void *priv)
101{
102 struct ieee80211_ccmp_data *_priv = priv;
103 if (_priv && _priv->tfm)
104 crypto_free_cipher((void*)_priv->tfm);
105 kfree(priv);
106}
107
108
109static inline void xor_block(u8 *b, u8 *a, size_t len)
110{
111 int i;
112 for (i = 0; i < len; i++)
113 b[i] ^= a[i];
114}
115
116
117
118static void ccmp_init_blocks(struct crypto_tfm *tfm,
119 struct ieee80211_hdr_4addr *hdr,
120 u8 *pn, size_t dlen, u8 *b0, u8 *auth,
121 u8 *s0)
122{
123 u8 *pos, qc = 0;
124 size_t aad_len;
125 u16 fc;
126 int a4_included, qc_included;
127 u8 aad[2 * AES_BLOCK_LEN];
128
129 fc = le16_to_cpu(hdr->frame_ctl);
130 a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
131 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
132 /*
133 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
134 (WLAN_FC_GET_STYPE(fc) & 0x08));
135 */
136 // fixed by David :2006.9.6
137 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
138 (WLAN_FC_GET_STYPE(fc) & 0x80));
139 aad_len = 22;
140 if (a4_included)
141 aad_len += 6;
142 if (qc_included) {
143 pos = (u8 *) &hdr->addr4;
144 if (a4_included)
145 pos += 6;
146 qc = *pos & 0x0f;
147 aad_len += 2;
148 }
149 /* CCM Initial Block:
150 * Flag (Include authentication header, M=3 (8-octet MIC),
151 * L=1 (2-octet Dlen))
152 * Nonce: 0x00 | A2 | PN
153 * Dlen */
154 b0[0] = 0x59;
155 b0[1] = qc;
156 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
157 memcpy(b0 + 8, pn, CCMP_PN_LEN);
158 b0[14] = (dlen >> 8) & 0xff;
159 b0[15] = dlen & 0xff;
160
161 /* AAD:
162 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
163 * A1 | A2 | A3
164 * SC with bits 4..15 (seq#) masked to zero
165 * A4 (if present)
166 * QC (if present)
167 */
168 pos = (u8 *) hdr;
169 aad[0] = 0; /* aad_len >> 8 */
170 aad[1] = aad_len & 0xff;
171 aad[2] = pos[0] & 0x8f;
172 aad[3] = pos[1] & 0xc7;
173 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
174 pos = (u8 *) &hdr->seq_ctl;
175 aad[22] = pos[0] & 0x0f;
176 aad[23] = 0; /* all bits masked */
177 memset(aad + 24, 0, 8);
178 if (a4_included)
179 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
180 if (qc_included) {
181 aad[a4_included ? 30 : 24] = qc;
182 /* rest of QC masked */
183 }
184
185 /* Start with the first block and AAD */
186 ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
187 xor_block(auth, aad, AES_BLOCK_LEN);
188 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
189 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
190 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
191 b0[0] &= 0x07;
192 b0[14] = b0[15] = 0;
193 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
194}
195
196
197
198static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
199{
200 struct ieee80211_ccmp_data *key = priv;
201 int data_len, i;
202 u8 *pos;
203 struct ieee80211_hdr_4addr *hdr;
204 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
205
206 if (skb_headroom(skb) < CCMP_HDR_LEN ||
207 skb_tailroom(skb) < CCMP_MIC_LEN ||
208 skb->len < hdr_len)
209 return -1;
210
211 data_len = skb->len - hdr_len;
212 pos = skb_push(skb, CCMP_HDR_LEN);
213 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
214 pos += hdr_len;
215// mic = skb_put(skb, CCMP_MIC_LEN);
216
217 i = CCMP_PN_LEN - 1;
218 while (i >= 0) {
219 key->tx_pn[i]++;
220 if (key->tx_pn[i] != 0)
221 break;
222 i--;
223 }
224
225 *pos++ = key->tx_pn[5];
226 *pos++ = key->tx_pn[4];
227 *pos++ = 0;
228 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
229 *pos++ = key->tx_pn[3];
230 *pos++ = key->tx_pn[2];
231 *pos++ = key->tx_pn[1];
232 *pos++ = key->tx_pn[0];
233
234
235 hdr = (struct ieee80211_hdr_4addr *) skb->data;
236 if (!tcb_desc->bHwSec)
237 {
238 int blocks, last, len;
239 u8 *mic;
240 u8 *b0 = key->tx_b0;
241 u8 *b = key->tx_b;
242 u8 *e = key->tx_e;
243 u8 *s0 = key->tx_s0;
244
245 //mic is moved to here by john
246 mic = skb_put(skb, CCMP_MIC_LEN);
247
248 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
249
250 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
251 last = data_len % AES_BLOCK_LEN;
252
253 for (i = 1; i <= blocks; i++) {
254 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
255 /* Authentication */
256 xor_block(b, pos, len);
257 ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
258 /* Encryption, with counter */
259 b0[14] = (i >> 8) & 0xff;
260 b0[15] = i & 0xff;
261 ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
262 xor_block(pos, e, len);
263 pos += len;
264 }
265
266 for (i = 0; i < CCMP_MIC_LEN; i++)
267 mic[i] = b[i] ^ s0[i];
268 }
269 return 0;
270}
271
272
273static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
274{
275 struct ieee80211_ccmp_data *key = priv;
276 u8 keyidx, *pos;
277 struct ieee80211_hdr_4addr *hdr;
278 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
279 u8 pn[6];
280
281 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
282 key->dot11RSNAStatsCCMPFormatErrors++;
283 return -1;
284 }
285
286 hdr = (struct ieee80211_hdr_4addr *) skb->data;
287 pos = skb->data + hdr_len;
288 keyidx = pos[3];
289 if (!(keyidx & (1 << 5))) {
290 if (net_ratelimit()) {
291 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
292 " flag from %pM\n", hdr->addr2);
293 }
294 key->dot11RSNAStatsCCMPFormatErrors++;
295 return -2;
296 }
297 keyidx >>= 6;
298 if (key->key_idx != keyidx) {
299 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
300 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
301 return -6;
302 }
303 if (!key->key_set) {
304 if (net_ratelimit()) {
305 printk(KERN_DEBUG "CCMP: received packet from %pM"
306 " with keyid=%d that does not have a configured"
307 " key\n", hdr->addr2, keyidx);
308 }
309 return -3;
310 }
311
312 pn[0] = pos[7];
313 pn[1] = pos[6];
314 pn[2] = pos[5];
315 pn[3] = pos[4];
316 pn[4] = pos[1];
317 pn[5] = pos[0];
318 pos += 8;
319
320 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
321 key->dot11RSNAStatsCCMPReplays++;
322 return -4;
323 }
324 if (!tcb_desc->bHwSec)
325 {
326 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
327 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
328 u8 *b0 = key->rx_b0;
329 u8 *b = key->rx_b;
330 u8 *a = key->rx_a;
331 int i, blocks, last, len;
332
333
334 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
335 xor_block(mic, b, CCMP_MIC_LEN);
336
337 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
338 last = data_len % AES_BLOCK_LEN;
339
340 for (i = 1; i <= blocks; i++) {
341 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
342 /* Decrypt, with counter */
343 b0[14] = (i >> 8) & 0xff;
344 b0[15] = i & 0xff;
345 ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
346 xor_block(pos, b, len);
347 /* Authentication */
348 xor_block(a, pos, len);
349 ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
350 pos += len;
351 }
352
353 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
354 if (net_ratelimit()) {
355 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
356 "%pM\n", hdr->addr2);
357 }
358 key->dot11RSNAStatsCCMPDecryptErrors++;
359 return -5;
360 }
361
362 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
363 }
364 /* Remove hdr and MIC */
365 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
366 skb_pull(skb, CCMP_HDR_LEN);
367 skb_trim(skb, skb->len - CCMP_MIC_LEN);
368
369 return keyidx;
370}
371
372
373static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
374{
375 struct ieee80211_ccmp_data *data = priv;
376 int keyidx;
377 struct crypto_tfm *tfm = data->tfm;
378
379 keyidx = data->key_idx;
380 memset(data, 0, sizeof(*data));
381 data->key_idx = keyidx;
382 data->tfm = tfm;
383 if (len == CCMP_TK_LEN) {
384 memcpy(data->key, key, CCMP_TK_LEN);
385 data->key_set = 1;
386 if (seq) {
387 data->rx_pn[0] = seq[5];
388 data->rx_pn[1] = seq[4];
389 data->rx_pn[2] = seq[3];
390 data->rx_pn[3] = seq[2];
391 data->rx_pn[4] = seq[1];
392 data->rx_pn[5] = seq[0];
393 }
394 crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN);
395 } else if (len == 0)
396 data->key_set = 0;
397 else
398 return -1;
399
400 return 0;
401}
402
403
404static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
405{
406 struct ieee80211_ccmp_data *data = priv;
407
408 if (len < CCMP_TK_LEN)
409 return -1;
410
411 if (!data->key_set)
412 return 0;
413 memcpy(key, data->key, CCMP_TK_LEN);
414
415 if (seq) {
416 seq[0] = data->tx_pn[5];
417 seq[1] = data->tx_pn[4];
418 seq[2] = data->tx_pn[3];
419 seq[3] = data->tx_pn[2];
420 seq[4] = data->tx_pn[1];
421 seq[5] = data->tx_pn[0];
422 }
423
424 return CCMP_TK_LEN;
425}
426
427
428static char * ieee80211_ccmp_print_stats(char *p, void *priv)
429{
430 struct ieee80211_ccmp_data *ccmp = priv;
431 int i;
432
433 p += sprintf(p, "key[%d] alg=CCMP key_set=%d tx_pn=",
434 ccmp->key_idx, ccmp->key_set);
435
436 for (i = 0; i < ARRAY_SIZE(ccmp->tx_pn); i++)
437 p += sprintf(p, "%02x", ccmp->tx_pn[i]);
438
439 sprintf(p, " rx_pn=");
440 for (i = 0; i < ARRAY_SIZE(ccmp->rx_pn); i++)
441 p += sprintf(p, "%02x", ccmp->tx_pn[i]);
442
443 p += sprintf(p, " format_errors=%d replays=%d decrypt_errors=%d\n",
444 ccmp->dot11RSNAStatsCCMPFormatErrors,
445 ccmp->dot11RSNAStatsCCMPReplays,
446 ccmp->dot11RSNAStatsCCMPDecryptErrors);
447
448 return p;
449}
450
451void ieee80211_ccmp_null(void)
452{
453 return;
454}
455
456static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
457 .name = "CCMP",
458 .init = ieee80211_ccmp_init,
459 .deinit = ieee80211_ccmp_deinit,
460 .encrypt_mpdu = ieee80211_ccmp_encrypt,
461 .decrypt_mpdu = ieee80211_ccmp_decrypt,
462 .encrypt_msdu = NULL,
463 .decrypt_msdu = NULL,
464 .set_key = ieee80211_ccmp_set_key,
465 .get_key = ieee80211_ccmp_get_key,
466 .print_stats = ieee80211_ccmp_print_stats,
467 .extra_prefix_len = CCMP_HDR_LEN,
468 .extra_postfix_len = CCMP_MIC_LEN,
469 .owner = THIS_MODULE,
470};
471
472
473int __init ieee80211_crypto_ccmp_init(void)
474{
475 return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
476}
477
478
479void ieee80211_crypto_ccmp_exit(void)
480{
481 ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
482}
483
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
new file mode 100644
index 00000000000..ed623a911e4
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -0,0 +1,809 @@
1/*
2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12//#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19#include <linux/if_ether.h>
20#include <linux/if_arp.h>
21#include <asm/string.h>
22
23#include "ieee80211.h"
24
25
26#include <linux/crypto.h>
27#include <linux/scatterlist.h>
28
29#include <linux/crc32.h>
30
31MODULE_AUTHOR("Jouni Malinen");
32MODULE_DESCRIPTION("Host AP crypt: TKIP");
33MODULE_LICENSE("GPL");
34
35#ifndef OPENSUSE_SLED
36#define OPENSUSE_SLED 0
37#endif
38
39struct ieee80211_tkip_data {
40#define TKIP_KEY_LEN 32
41 u8 key[TKIP_KEY_LEN];
42 int key_set;
43
44 u32 tx_iv32;
45 u16 tx_iv16;
46 u16 tx_ttak[5];
47 int tx_phase1_done;
48
49 u32 rx_iv32;
50 u16 rx_iv16;
51 u16 rx_ttak[5];
52 int rx_phase1_done;
53 u32 rx_iv32_new;
54 u16 rx_iv16_new;
55
56 u32 dot11RSNAStatsTKIPReplays;
57 u32 dot11RSNAStatsTKIPICVErrors;
58 u32 dot11RSNAStatsTKIPLocalMICFailures;
59
60 int key_idx;
61 struct crypto_blkcipher *rx_tfm_arc4;
62 struct crypto_hash *rx_tfm_michael;
63 struct crypto_blkcipher *tx_tfm_arc4;
64 struct crypto_hash *tx_tfm_michael;
65 /* scratch buffers for virt_to_page() (crypto API) */
66 u8 rx_hdr[16], tx_hdr[16];
67};
68
69static void * ieee80211_tkip_init(int key_idx)
70{
71 struct ieee80211_tkip_data *priv;
72
73 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
74 if (priv == NULL)
75 goto fail;
76 priv->key_idx = key_idx;
77 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
78 CRYPTO_ALG_ASYNC);
79 if (IS_ERR(priv->tx_tfm_arc4)) {
80 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
81 "crypto API arc4\n");
82 priv->tx_tfm_arc4 = NULL;
83 goto fail;
84 }
85
86 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
87 CRYPTO_ALG_ASYNC);
88 if (IS_ERR(priv->tx_tfm_michael)) {
89 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
90 "crypto API michael_mic\n");
91 priv->tx_tfm_michael = NULL;
92 goto fail;
93 }
94
95 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
96 CRYPTO_ALG_ASYNC);
97 if (IS_ERR(priv->rx_tfm_arc4)) {
98 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
99 "crypto API arc4\n");
100 priv->rx_tfm_arc4 = NULL;
101 goto fail;
102 }
103
104 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
105 CRYPTO_ALG_ASYNC);
106 if (IS_ERR(priv->rx_tfm_michael)) {
107 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
108 "crypto API michael_mic\n");
109 priv->rx_tfm_michael = NULL;
110 goto fail;
111 }
112 return priv;
113
114fail:
115 if (priv) {
116 if (priv->tx_tfm_michael)
117 crypto_free_hash(priv->tx_tfm_michael);
118 if (priv->tx_tfm_arc4)
119 crypto_free_blkcipher(priv->tx_tfm_arc4);
120 if (priv->rx_tfm_michael)
121 crypto_free_hash(priv->rx_tfm_michael);
122 if (priv->rx_tfm_arc4)
123 crypto_free_blkcipher(priv->rx_tfm_arc4);
124 kfree(priv);
125 }
126
127 return NULL;
128}
129
130
131static void ieee80211_tkip_deinit(void *priv)
132{
133 struct ieee80211_tkip_data *_priv = priv;
134 if (_priv) {
135 if (_priv->tx_tfm_michael)
136 crypto_free_hash(_priv->tx_tfm_michael);
137 if (_priv->tx_tfm_arc4)
138 crypto_free_blkcipher(_priv->tx_tfm_arc4);
139 if (_priv->rx_tfm_michael)
140 crypto_free_hash(_priv->rx_tfm_michael);
141 if (_priv->rx_tfm_arc4)
142 crypto_free_blkcipher(_priv->rx_tfm_arc4);
143 }
144 kfree(priv);
145}
146
147
148static inline u16 RotR1(u16 val)
149{
150 return (val >> 1) | (val << 15);
151}
152
153
154static inline u8 Lo8(u16 val)
155{
156 return val & 0xff;
157}
158
159
160static inline u8 Hi8(u16 val)
161{
162 return val >> 8;
163}
164
165
166static inline u16 Lo16(u32 val)
167{
168 return val & 0xffff;
169}
170
171
172static inline u16 Hi16(u32 val)
173{
174 return val >> 16;
175}
176
177
178static inline u16 Mk16(u8 hi, u8 lo)
179{
180 return lo | (((u16) hi) << 8);
181}
182
183
184static inline u16 Mk16_le(u16 *v)
185{
186 return le16_to_cpu(*v);
187}
188
189
190static const u16 Sbox[256] =
191{
192 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
193 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
194 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
195 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
196 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
197 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
198 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
199 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
200 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
201 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
202 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
203 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
204 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
205 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
206 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
207 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
208 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
209 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
210 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
211 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
212 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
213 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
214 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
215 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
216 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
217 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
218 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
219 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
220 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
221 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
222 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
223 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
224};
225
226
227static inline u16 _S_(u16 v)
228{
229 u16 t = Sbox[Hi8(v)];
230 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
231}
232
233
234#define PHASE1_LOOP_COUNT 8
235
236
237static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
238{
239 int i, j;
240
241 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
242 TTAK[0] = Lo16(IV32);
243 TTAK[1] = Hi16(IV32);
244 TTAK[2] = Mk16(TA[1], TA[0]);
245 TTAK[3] = Mk16(TA[3], TA[2]);
246 TTAK[4] = Mk16(TA[5], TA[4]);
247
248 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
249 j = 2 * (i & 1);
250 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
251 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
252 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
253 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
254 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
255 }
256}
257
258
259static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
260 u16 IV16)
261{
262 /* Make temporary area overlap WEP seed so that the final copy can be
263 * avoided on little endian hosts. */
264 u16 *PPK = (u16 *) &WEPSeed[4];
265
266 /* Step 1 - make copy of TTAK and bring in TSC */
267 PPK[0] = TTAK[0];
268 PPK[1] = TTAK[1];
269 PPK[2] = TTAK[2];
270 PPK[3] = TTAK[3];
271 PPK[4] = TTAK[4];
272 PPK[5] = TTAK[4] + IV16;
273
274 /* Step 2 - 96-bit bijective mixing using S-box */
275 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
276 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
277 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
278 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
279 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
280 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
281
282 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
283 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
284 PPK[2] += RotR1(PPK[1]);
285 PPK[3] += RotR1(PPK[2]);
286 PPK[4] += RotR1(PPK[3]);
287 PPK[5] += RotR1(PPK[4]);
288
289 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
290 * WEPSeed[0..2] is transmitted as WEP IV */
291 WEPSeed[0] = Hi8(IV16);
292 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
293 WEPSeed[2] = Lo8(IV16);
294 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
295
296#ifdef __BIG_ENDIAN
297 {
298 int i;
299 for (i = 0; i < 6; i++)
300 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
301 }
302#endif
303}
304
305
306static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
307{
308 struct ieee80211_tkip_data *tkey = priv;
309 int len;
310 u8 *pos;
311 struct ieee80211_hdr_4addr *hdr;
312 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
313
314 struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
315 int ret = 0;
316 u8 rc4key[16], *icv;
317 u32 crc;
318 struct scatterlist sg;
319
320 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
321 skb->len < hdr_len)
322 return -1;
323
324 hdr = (struct ieee80211_hdr_4addr *) skb->data;
325
326 if (!tcb_desc->bHwSec)
327 {
328 if (!tkey->tx_phase1_done) {
329 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
330 tkey->tx_iv32);
331 tkey->tx_phase1_done = 1;
332 }
333 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
334 }
335 else
336 tkey->tx_phase1_done = 1;
337
338
339 len = skb->len - hdr_len;
340 pos = skb_push(skb, 8);
341 memmove(pos, pos + 8, hdr_len);
342 pos += hdr_len;
343
344 if (tcb_desc->bHwSec)
345 {
346 *pos++ = Hi8(tkey->tx_iv16);
347 *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
348 *pos++ = Lo8(tkey->tx_iv16);
349 }
350 else
351 {
352 *pos++ = rc4key[0];
353 *pos++ = rc4key[1];
354 *pos++ = rc4key[2];
355 }
356
357 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
358 *pos++ = tkey->tx_iv32 & 0xff;
359 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
360 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
361 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
362
363 if (!tcb_desc->bHwSec)
364 {
365 icv = skb_put(skb, 4);
366 crc = ~crc32_le(~0, pos, len);
367 icv[0] = crc;
368 icv[1] = crc >> 8;
369 icv[2] = crc >> 16;
370 icv[3] = crc >> 24;
371 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
372 sg_init_one(&sg, pos, len+4);
373 ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
374
375 }
376
377 tkey->tx_iv16++;
378 if (tkey->tx_iv16 == 0) {
379 tkey->tx_phase1_done = 0;
380 tkey->tx_iv32++;
381 }
382
383 if (!tcb_desc->bHwSec)
384 return ret;
385 else
386 return 0;
387
388
389}
390
391static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
392{
393 struct ieee80211_tkip_data *tkey = priv;
394 u8 keyidx, *pos;
395 u32 iv32;
396 u16 iv16;
397 struct ieee80211_hdr_4addr *hdr;
398 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
399 struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4};
400 u8 rc4key[16];
401 u8 icv[4];
402 u32 crc;
403 struct scatterlist sg;
404 int plen;
405 if (skb->len < hdr_len + 8 + 4)
406 return -1;
407
408 hdr = (struct ieee80211_hdr_4addr *) skb->data;
409 pos = skb->data + hdr_len;
410 keyidx = pos[3];
411 if (!(keyidx & (1 << 5))) {
412 if (net_ratelimit()) {
413 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
414 " flag from %pM\n", hdr->addr2);
415 }
416 return -2;
417 }
418 keyidx >>= 6;
419 if (tkey->key_idx != keyidx) {
420 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
421 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
422 return -6;
423 }
424 if (!tkey->key_set) {
425 if (net_ratelimit()) {
426 printk(KERN_DEBUG "TKIP: received packet from %pM"
427 " with keyid=%d that does not have a configured"
428 " key\n", hdr->addr2, keyidx);
429 }
430 return -3;
431 }
432 iv16 = (pos[0] << 8) | pos[2];
433 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
434 pos += 8;
435
436 if (!tcb_desc->bHwSec)
437 {
438 if (iv32 < tkey->rx_iv32 ||
439 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
440 if (net_ratelimit()) {
441 printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
442 " previous TSC %08x%04x received TSC "
443 "%08x%04x\n", hdr->addr2,
444 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
445 }
446 tkey->dot11RSNAStatsTKIPReplays++;
447 return -4;
448 }
449
450 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
451 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
452 tkey->rx_phase1_done = 1;
453 }
454 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
455
456 plen = skb->len - hdr_len - 12;
457
458 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
459 sg_init_one(&sg, pos, plen+4);
460 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
461 if (net_ratelimit()) {
462 printk(KERN_DEBUG ": TKIP: failed to decrypt "
463 "received packet from %pM\n",
464 hdr->addr2);
465 }
466 return -7;
467 }
468
469 crc = ~crc32_le(~0, pos, plen);
470 icv[0] = crc;
471 icv[1] = crc >> 8;
472 icv[2] = crc >> 16;
473 icv[3] = crc >> 24;
474
475 if (memcmp(icv, pos + plen, 4) != 0) {
476 if (iv32 != tkey->rx_iv32) {
477 /* Previously cached Phase1 result was already lost, so
478 * it needs to be recalculated for the next packet. */
479 tkey->rx_phase1_done = 0;
480 }
481 if (net_ratelimit()) {
482 printk(KERN_DEBUG
483 "TKIP: ICV error detected: STA=%pM\n",
484 hdr->addr2);
485 }
486 tkey->dot11RSNAStatsTKIPICVErrors++;
487 return -5;
488 }
489
490 }
491
492 /* Update real counters only after Michael MIC verification has
493 * completed */
494 tkey->rx_iv32_new = iv32;
495 tkey->rx_iv16_new = iv16;
496
497 /* Remove IV and ICV */
498 memmove(skb->data + 8, skb->data, hdr_len);
499 skb_pull(skb, 8);
500 skb_trim(skb, skb->len - 4);
501
502 return keyidx;
503}
504
505
506static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
507 u8 * data, size_t data_len, u8 * mic)
508{
509 struct hash_desc desc;
510 struct scatterlist sg[2];
511
512 if (tfm_michael == NULL) {
513 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
514 return -1;
515 }
516 sg_init_table(sg, 2);
517 sg_set_buf(&sg[0], hdr, 16);
518 sg_set_buf(&sg[1], data, data_len);
519
520 if (crypto_hash_setkey(tfm_michael, key, 8))
521 return -1;
522
523 desc.tfm = tfm_michael;
524 desc.flags = 0;
525 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
526}
527
528
529
530static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
531{
532 struct ieee80211_hdr_4addr *hdr11;
533
534 hdr11 = (struct ieee80211_hdr_4addr *) skb->data;
535 switch (le16_to_cpu(hdr11->frame_ctl) &
536 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
537 case IEEE80211_FCTL_TODS:
538 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
539 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
540 break;
541 case IEEE80211_FCTL_FROMDS:
542 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
543 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
544 break;
545 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
546 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
547 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
548 break;
549 case 0:
550 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
551 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
552 break;
553 }
554
555 hdr[12] = 0; /* priority */
556
557 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
558}
559
560
561static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
562{
563 struct ieee80211_tkip_data *tkey = priv;
564 u8 *pos;
565 struct ieee80211_hdr_4addr *hdr;
566
567 hdr = (struct ieee80211_hdr_4addr *) skb->data;
568
569 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
570 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
571 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
572 skb_tailroom(skb), hdr_len, skb->len);
573 return -1;
574 }
575
576 michael_mic_hdr(skb, tkey->tx_hdr);
577
578 // { david, 2006.9.1
579 // fix the wpa process with wmm enabled.
580 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
581 tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
582 }
583 // }
584 pos = skb_put(skb, 8);
585 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
586 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
587 return -1;
588
589 return 0;
590}
591
592
593#if WIRELESS_EXT >= 18
594static void ieee80211_michael_mic_failure(struct net_device *dev,
595 struct ieee80211_hdr_4addr *hdr,
596 int keyidx)
597{
598 union iwreq_data wrqu;
599 struct iw_michaelmicfailure ev;
600
601 /* TODO: needed parameters: count, keyid, key type, TSC */
602 memset(&ev, 0, sizeof(ev));
603 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
604 if (hdr->addr1[0] & 0x01)
605 ev.flags |= IW_MICFAILURE_GROUP;
606 else
607 ev.flags |= IW_MICFAILURE_PAIRWISE;
608 ev.src_addr.sa_family = ARPHRD_ETHER;
609 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
610 memset(&wrqu, 0, sizeof(wrqu));
611 wrqu.data.length = sizeof(ev);
612 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
613}
614#elif WIRELESS_EXT >= 15
615static void ieee80211_michael_mic_failure(struct net_device *dev,
616 struct ieee80211_hdr_4addr *hdr,
617 int keyidx)
618{
619 union iwreq_data wrqu;
620 char buf[128];
621
622 /* TODO: needed parameters: count, keyid, key type, TSC */
623 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
624 "%pM)", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
625 hdr->addr2);
626 memset(&wrqu, 0, sizeof(wrqu));
627 wrqu.data.length = strlen(buf);
628 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
629}
630#else /* WIRELESS_EXT >= 15 */
631static inline void ieee80211_michael_mic_failure(struct net_device *dev,
632 struct ieee80211_hdr_4addr *hdr,
633 int keyidx)
634{
635}
636#endif /* WIRELESS_EXT >= 15 */
637
638static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
639 int hdr_len, void *priv)
640{
641 struct ieee80211_tkip_data *tkey = priv;
642 u8 mic[8];
643 struct ieee80211_hdr_4addr *hdr;
644
645 hdr = (struct ieee80211_hdr_4addr *) skb->data;
646
647 if (!tkey->key_set)
648 return -1;
649
650 michael_mic_hdr(skb, tkey->rx_hdr);
651 // { david, 2006.9.1
652 // fix the wpa process with wmm enabled.
653 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
654 tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
655 }
656 // }
657
658 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
659 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
660 return -1;
661 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
662 struct ieee80211_hdr_4addr *hdr;
663 hdr = (struct ieee80211_hdr_4addr *) skb->data;
664 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
665 "MSDU from %pM keyidx=%d\n",
666 skb->dev ? skb->dev->name : "N/A", hdr->addr2,
667 keyidx);
668 if (skb->dev)
669 ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
670 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
671 return -1;
672 }
673
674 /* Update TSC counters for RX now that the packet verification has
675 * completed. */
676 tkey->rx_iv32 = tkey->rx_iv32_new;
677 tkey->rx_iv16 = tkey->rx_iv16_new;
678
679 skb_trim(skb, skb->len - 8);
680
681 return 0;
682}
683
684
685static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
686{
687 struct ieee80211_tkip_data *tkey = priv;
688 int keyidx;
689 struct crypto_hash *tfm = tkey->tx_tfm_michael;
690 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
691 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
692 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
693
694 keyidx = tkey->key_idx;
695 memset(tkey, 0, sizeof(*tkey));
696 tkey->key_idx = keyidx;
697 tkey->tx_tfm_michael = tfm;
698 tkey->tx_tfm_arc4 = tfm2;
699 tkey->rx_tfm_michael = tfm3;
700 tkey->rx_tfm_arc4 = tfm4;
701
702 if (len == TKIP_KEY_LEN) {
703 memcpy(tkey->key, key, TKIP_KEY_LEN);
704 tkey->key_set = 1;
705 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
706 if (seq) {
707 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
708 (seq[3] << 8) | seq[2];
709 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
710 }
711 } else if (len == 0)
712 tkey->key_set = 0;
713 else
714 return -1;
715
716 return 0;
717}
718
719
720static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
721{
722 struct ieee80211_tkip_data *tkey = priv;
723
724 if (len < TKIP_KEY_LEN)
725 return -1;
726
727 if (!tkey->key_set)
728 return 0;
729 memcpy(key, tkey->key, TKIP_KEY_LEN);
730
731 if (seq) {
732 /* Return the sequence number of the last transmitted frame. */
733 u16 iv16 = tkey->tx_iv16;
734 u32 iv32 = tkey->tx_iv32;
735 if (iv16 == 0)
736 iv32--;
737 iv16--;
738 seq[0] = tkey->tx_iv16;
739 seq[1] = tkey->tx_iv16 >> 8;
740 seq[2] = tkey->tx_iv32;
741 seq[3] = tkey->tx_iv32 >> 8;
742 seq[4] = tkey->tx_iv32 >> 16;
743 seq[5] = tkey->tx_iv32 >> 24;
744 }
745
746 return TKIP_KEY_LEN;
747}
748
749
750static char * ieee80211_tkip_print_stats(char *p, void *priv)
751{
752 struct ieee80211_tkip_data *tkip = priv;
753 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
754 "tx_pn=%02x%02x%02x%02x%02x%02x "
755 "rx_pn=%02x%02x%02x%02x%02x%02x "
756 "replays=%d icv_errors=%d local_mic_failures=%d\n",
757 tkip->key_idx, tkip->key_set,
758 (tkip->tx_iv32 >> 24) & 0xff,
759 (tkip->tx_iv32 >> 16) & 0xff,
760 (tkip->tx_iv32 >> 8) & 0xff,
761 tkip->tx_iv32 & 0xff,
762 (tkip->tx_iv16 >> 8) & 0xff,
763 tkip->tx_iv16 & 0xff,
764 (tkip->rx_iv32 >> 24) & 0xff,
765 (tkip->rx_iv32 >> 16) & 0xff,
766 (tkip->rx_iv32 >> 8) & 0xff,
767 tkip->rx_iv32 & 0xff,
768 (tkip->rx_iv16 >> 8) & 0xff,
769 tkip->rx_iv16 & 0xff,
770 tkip->dot11RSNAStatsTKIPReplays,
771 tkip->dot11RSNAStatsTKIPICVErrors,
772 tkip->dot11RSNAStatsTKIPLocalMICFailures);
773 return p;
774}
775
776
777static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
778 .name = "TKIP",
779 .init = ieee80211_tkip_init,
780 .deinit = ieee80211_tkip_deinit,
781 .encrypt_mpdu = ieee80211_tkip_encrypt,
782 .decrypt_mpdu = ieee80211_tkip_decrypt,
783 .encrypt_msdu = ieee80211_michael_mic_add,
784 .decrypt_msdu = ieee80211_michael_mic_verify,
785 .set_key = ieee80211_tkip_set_key,
786 .get_key = ieee80211_tkip_get_key,
787 .print_stats = ieee80211_tkip_print_stats,
788 .extra_prefix_len = 4 + 4, /* IV + ExtIV */
789 .extra_postfix_len = 8 + 4, /* MIC + ICV */
790 .owner = THIS_MODULE,
791};
792
793
794int __init ieee80211_crypto_tkip_init(void)
795{
796 return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
797}
798
799
800void ieee80211_crypto_tkip_exit(void)
801{
802 ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
803}
804
805void ieee80211_tkip_null(void)
806{
807 return;
808}
809
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
new file mode 100644
index 00000000000..55043913afc
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
@@ -0,0 +1,296 @@
1/*
2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/slab.h>
15#include <linux/random.h>
16#include <linux/skbuff.h>
17#include <asm/string.h>
18
19#include "ieee80211.h"
20
21
22#include <linux/crypto.h>
23
24#include <linux/scatterlist.h>
25#include <linux/crc32.h>
26
27MODULE_AUTHOR("Jouni Malinen");
28MODULE_DESCRIPTION("Host AP crypt: WEP");
29MODULE_LICENSE("GPL");
30#ifndef OPENSUSE_SLED
31#define OPENSUSE_SLED 0
32#endif
33
34struct prism2_wep_data {
35 u32 iv;
36#define WEP_KEY_LEN 13
37 u8 key[WEP_KEY_LEN + 1];
38 u8 key_len;
39 u8 key_idx;
40 struct crypto_blkcipher *tx_tfm;
41 struct crypto_blkcipher *rx_tfm;
42};
43
44
45static void * prism2_wep_init(int keyidx)
46{
47 struct prism2_wep_data *priv;
48
49 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
50 if (priv == NULL)
51 goto fail;
52 priv->key_idx = keyidx;
53
54 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
55 if (IS_ERR(priv->tx_tfm)) {
56 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
57 "crypto API arc4\n");
58 priv->tx_tfm = NULL;
59 goto fail;
60 }
61 priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
62 if (IS_ERR(priv->rx_tfm)) {
63 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
64 "crypto API arc4\n");
65 priv->rx_tfm = NULL;
66 goto fail;
67 }
68
69 /* start WEP IV from a random value */
70 get_random_bytes(&priv->iv, 4);
71
72 return priv;
73
74fail:
75 if (priv) {
76 if (priv->tx_tfm)
77 crypto_free_blkcipher(priv->tx_tfm);
78 if (priv->rx_tfm)
79 crypto_free_blkcipher(priv->rx_tfm);
80 kfree(priv);
81 }
82 return NULL;
83}
84
85
86static void prism2_wep_deinit(void *priv)
87{
88 struct prism2_wep_data *_priv = priv;
89 if (_priv) {
90 if (_priv->tx_tfm)
91 crypto_free_blkcipher(_priv->tx_tfm);
92 if (_priv->rx_tfm)
93 crypto_free_blkcipher(_priv->rx_tfm);
94 }
95 kfree(priv);
96}
97
98/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
99 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
100 * so the payload length increases with 8 bytes.
101 *
102 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
103 */
104static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
105{
106 struct prism2_wep_data *wep = priv;
107 u32 klen, len;
108 u8 key[WEP_KEY_LEN + 3];
109 u8 *pos;
110 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
111 struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
112 u32 crc;
113 u8 *icv;
114 struct scatterlist sg;
115 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
116 skb->len < hdr_len)
117 return -1;
118
119 len = skb->len - hdr_len;
120 pos = skb_push(skb, 4);
121 memmove(pos, pos + 4, hdr_len);
122 pos += hdr_len;
123
124 klen = 3 + wep->key_len;
125
126 wep->iv++;
127
128 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
129 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
130 * can be used to speedup attacks, so avoid using them. */
131 if ((wep->iv & 0xff00) == 0xff00) {
132 u8 B = (wep->iv >> 16) & 0xff;
133 if (B >= 3 && B < klen)
134 wep->iv += 0x0100;
135 }
136
137 /* Prepend 24-bit IV to RC4 key and TX frame */
138 *pos++ = key[0] = (wep->iv >> 16) & 0xff;
139 *pos++ = key[1] = (wep->iv >> 8) & 0xff;
140 *pos++ = key[2] = wep->iv & 0xff;
141 *pos++ = wep->key_idx << 6;
142
143 /* Copy rest of the WEP key (the secret part) */
144 memcpy(key + 3, wep->key, wep->key_len);
145
146 if (!tcb_desc->bHwSec)
147 {
148
149 /* Append little-endian CRC32 and encrypt it to produce ICV */
150 crc = ~crc32_le(~0, pos, len);
151 icv = skb_put(skb, 4);
152 icv[0] = crc;
153 icv[1] = crc >> 8;
154 icv[2] = crc >> 16;
155 icv[3] = crc >> 24;
156
157 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
158 sg_init_one(&sg, pos, len+4);
159 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
160 }
161
162 return 0;
163}
164
165
166/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
167 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
168 * ICV (4 bytes). len includes both IV and ICV.
169 *
170 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
171 * failure. If frame is OK, IV and ICV will be removed.
172 */
173static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
174{
175 struct prism2_wep_data *wep = priv;
176 u32 klen, plen;
177 u8 key[WEP_KEY_LEN + 3];
178 u8 keyidx, *pos;
179 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
180 struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
181 u32 crc;
182 u8 icv[4];
183 struct scatterlist sg;
184 if (skb->len < hdr_len + 8)
185 return -1;
186
187 pos = skb->data + hdr_len;
188 key[0] = *pos++;
189 key[1] = *pos++;
190 key[2] = *pos++;
191 keyidx = *pos++ >> 6;
192 if (keyidx != wep->key_idx)
193 return -1;
194
195 klen = 3 + wep->key_len;
196
197 /* Copy rest of the WEP key (the secret part) */
198 memcpy(key + 3, wep->key, wep->key_len);
199
200 /* Apply RC4 to data and compute CRC32 over decrypted data */
201 plen = skb->len - hdr_len - 8;
202
203 if (!tcb_desc->bHwSec)
204 {
205 crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
206 sg_init_one(&sg, pos, plen+4);
207 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
208 return -7;
209 crc = ~crc32_le(~0, pos, plen);
210 icv[0] = crc;
211 icv[1] = crc >> 8;
212 icv[2] = crc >> 16;
213 icv[3] = crc >> 24;
214 if (memcmp(icv, pos + plen, 4) != 0) {
215 /* ICV mismatch - drop frame */
216 return -2;
217 }
218 }
219 /* Remove IV and ICV */
220 memmove(skb->data + 4, skb->data, hdr_len);
221 skb_pull(skb, 4);
222 skb_trim(skb, skb->len - 4);
223
224 return 0;
225}
226
227
228static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
229{
230 struct prism2_wep_data *wep = priv;
231
232 if (len < 0 || len > WEP_KEY_LEN)
233 return -1;
234
235 memcpy(wep->key, key, len);
236 wep->key_len = len;
237
238 return 0;
239}
240
241
242static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
243{
244 struct prism2_wep_data *wep = priv;
245
246 if (len < wep->key_len)
247 return -1;
248
249 memcpy(key, wep->key, wep->key_len);
250
251 return wep->key_len;
252}
253
254
255static char * prism2_wep_print_stats(char *p, void *priv)
256{
257 struct prism2_wep_data *wep = priv;
258 p += sprintf(p, "key[%d] alg=WEP len=%d\n",
259 wep->key_idx, wep->key_len);
260 return p;
261}
262
263
264static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
265 .name = "WEP",
266 .init = prism2_wep_init,
267 .deinit = prism2_wep_deinit,
268 .encrypt_mpdu = prism2_wep_encrypt,
269 .decrypt_mpdu = prism2_wep_decrypt,
270 .encrypt_msdu = NULL,
271 .decrypt_msdu = NULL,
272 .set_key = prism2_wep_set_key,
273 .get_key = prism2_wep_get_key,
274 .print_stats = prism2_wep_print_stats,
275 .extra_prefix_len = 4, /* IV */
276 .extra_postfix_len = 4, /* ICV */
277 .owner = THIS_MODULE,
278};
279
280
281int __init ieee80211_crypto_wep_init(void)
282{
283 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
284}
285
286
287void __exit ieee80211_crypto_wep_exit(void)
288{
289 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
290}
291
292void ieee80211_wep_null(void)
293{
294 return;
295}
296
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
new file mode 100644
index 00000000000..37a65ff4b12
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
@@ -0,0 +1,352 @@
1/*******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
34#include <linux/errno.h>
35#include <linux/if_arp.h>
36#include <linux/in6.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/netdevice.h>
42#include <linux/pci.h>
43#include <linux/proc_fs.h>
44#include <linux/skbuff.h>
45#include <linux/slab.h>
46#include <linux/tcp.h>
47#include <linux/types.h>
48#include <linux/wireless.h>
49#include <linux/etherdevice.h>
50#include <asm/uaccess.h>
51#include <net/arp.h>
52
53#include "ieee80211.h"
54
55MODULE_DESCRIPTION("802.11 data/management/control stack");
56MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
57MODULE_LICENSE("GPL");
58
59#define DRV_NAME "ieee80211"
60
61static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
62{
63 if (ieee->networks)
64 return 0;
65
66 ieee->networks = kcalloc(
67 MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
68 GFP_KERNEL);
69 if (!ieee->networks) {
70 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
71 ieee->dev->name);
72 return -ENOMEM;
73 }
74
75 return 0;
76}
77
78static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
79{
80 if (!ieee->networks)
81 return;
82 kfree(ieee->networks);
83 ieee->networks = NULL;
84}
85
86static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
87{
88 int i;
89
90 INIT_LIST_HEAD(&ieee->network_free_list);
91 INIT_LIST_HEAD(&ieee->network_list);
92 for (i = 0; i < MAX_NETWORK_COUNT; i++)
93 list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
94}
95
96
97struct net_device *alloc_ieee80211(int sizeof_priv)
98{
99 struct ieee80211_device *ieee;
100 struct net_device *dev;
101 int i, err;
102
103 IEEE80211_DEBUG_INFO("Initializing...\n");
104
105 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
106 if (!dev) {
107 IEEE80211_ERROR("Unable to network device.\n");
108 goto failed;
109 }
110
111 ieee = netdev_priv(dev);
112
113 memset(ieee, 0, sizeof(struct ieee80211_device) + sizeof_priv);
114 ieee->dev = dev;
115
116 err = ieee80211_networks_allocate(ieee);
117 if (err) {
118 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
119 err);
120 goto failed;
121 }
122 ieee80211_networks_initialize(ieee);
123
124
125 /* Default fragmentation threshold is maximum payload size */
126 ieee->fts = DEFAULT_FTS;
127 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
128 ieee->open_wep = 1;
129
130 /* Default to enabling full open WEP with host based encrypt/decrypt */
131 ieee->host_encrypt = 1;
132 ieee->host_decrypt = 1;
133 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
134
135 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
136 init_timer(&ieee->crypt_deinit_timer);
137 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
138 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
139
140 spin_lock_init(&ieee->lock);
141 spin_lock_init(&ieee->wpax_suitlist_lock);
142 spin_lock_init(&ieee->bw_spinlock);
143 spin_lock_init(&ieee->reorder_spinlock);
144
145 /* added by WB */
146 atomic_set(&(ieee->atm_chnlop), 0);
147 atomic_set(&(ieee->atm_swbw), 0);
148
149 ieee->wpax_type_set = 0;
150 ieee->wpa_enabled = 0;
151 ieee->tkip_countermeasures = 0;
152 ieee->drop_unencrypted = 0;
153 ieee->privacy_invoked = 0;
154 ieee->ieee802_1x = 1;
155 ieee->raw_tx = 0;
156 /* ieee->hwsec_support = 1; default support hw security: use module_param instead */
157 ieee->hwsec_active = 0; /* disable hwsec, switch it on when necessary */
158
159 ieee80211_softmac_init(ieee);
160
161 ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
162 if (ieee->pHTInfo == NULL)
163 {
164 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
165 return NULL;
166 }
167 HTUpdateDefaultSetting(ieee);
168 HTInitializeHTInfo(ieee); /* may move to other place */
169 TSInitialize(ieee);
170 for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
171 INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
172
173 for (i = 0; i < 17; i++) {
174 ieee->last_rxseq_num[i] = -1;
175 ieee->last_rxfrag_num[i] = -1;
176 ieee->last_packet_time[i] = 0;
177 }
178
179 /* Functions to load crypt module automatically */
180 ieee80211_tkip_null();
181 ieee80211_wep_null();
182 ieee80211_ccmp_null();
183
184 return dev;
185
186failed:
187 if (dev)
188 free_netdev(dev);
189 return NULL;
190}
191
192
193void free_ieee80211(struct net_device *dev)
194{
195 struct ieee80211_device *ieee = netdev_priv(dev);
196 int i;
197 kfree(ieee->pHTInfo);
198 ieee->pHTInfo = NULL;
199 RemoveAllTS(ieee);
200 ieee80211_softmac_free(ieee);
201 del_timer_sync(&ieee->crypt_deinit_timer);
202 ieee80211_crypt_deinit_entries(ieee, 1);
203
204 for (i = 0; i < WEP_KEYS; i++) {
205 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
206 if (crypt) {
207 if (crypt->ops)
208 crypt->ops->deinit(crypt->priv);
209 kfree(crypt);
210 ieee->crypt[i] = NULL;
211 }
212 }
213
214 ieee80211_networks_free(ieee);
215 free_netdev(dev);
216}
217
218#ifdef CONFIG_IEEE80211_DEBUG
219
220u32 ieee80211_debug_level = 0;
221static int debug =
222 /* IEEE80211_DL_INFO | */
223 /* IEEE80211_DL_WX | */
224 /* IEEE80211_DL_SCAN | */
225 /* IEEE80211_DL_STATE | */
226 /* IEEE80211_DL_MGMT | */
227 /* IEEE80211_DL_FRAG | */
228 /* IEEE80211_DL_EAP | */
229 /* IEEE80211_DL_DROP | */
230 /* IEEE80211_DL_TX | */
231 /* IEEE80211_DL_RX | */
232 /* IEEE80211_DL_QOS | */
233 /* IEEE80211_DL_HT | */
234 /* IEEE80211_DL_TS | */
235 /* IEEE80211_DL_BA | */
236 /* IEEE80211_DL_REORDER | */
237 /* IEEE80211_DL_TRACE | */
238 /* IEEE80211_DL_DATA | */
239 IEEE80211_DL_ERR /* always open this flag to show error out */
240 ;
241struct proc_dir_entry *ieee80211_proc = NULL;
242
243static int show_debug_level(char *page, char **start, off_t offset,
244 int count, int *eof, void *data)
245{
246 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
247}
248
249static int store_debug_level(struct file *file, const char *buffer,
250 unsigned long count, void *data)
251{
252 char buf[] = "0x00000000";
253 unsigned long len = min(sizeof(buf) - 1, (u32)count);
254 char *p = (char *)buf;
255 unsigned long val;
256
257 if (copy_from_user(buf, buffer, len))
258 return count;
259 buf[len] = 0;
260 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
261 p++;
262 if (p[0] == 'x' || p[0] == 'X')
263 p++;
264 val = simple_strtoul(p, &p, 16);
265 } else
266 val = simple_strtoul(p, &p, 10);
267 if (p == buf)
268 printk(KERN_INFO DRV_NAME
269 ": %s is not in hex or decimal form.\n", buf);
270 else
271 ieee80211_debug_level = val;
272
273 return strnlen(buf, count);
274}
275
276extern int ieee80211_crypto_init(void);
277extern void ieee80211_crypto_deinit(void);
278extern int ieee80211_crypto_tkip_init(void);
279extern void ieee80211_crypto_tkip_exit(void);
280extern int ieee80211_crypto_ccmp_init(void);
281extern void ieee80211_crypto_ccmp_exit(void);
282extern int ieee80211_crypto_wep_init(void);
283extern void ieee80211_crypto_wep_exit(void);
284
285int __init ieee80211_rtl_init(void)
286{
287 struct proc_dir_entry *e;
288 int retval;
289
290 retval = ieee80211_crypto_init();
291 if (retval)
292 return retval;
293 retval = ieee80211_crypto_tkip_init();
294 if (retval) {
295 ieee80211_crypto_deinit();
296 return retval;
297 }
298 retval = ieee80211_crypto_ccmp_init();
299 if (retval) {
300 ieee80211_crypto_tkip_exit();
301 ieee80211_crypto_deinit();
302 return retval;
303 }
304 retval = ieee80211_crypto_wep_init();
305 if (retval) {
306 ieee80211_crypto_ccmp_exit();
307 ieee80211_crypto_tkip_exit();
308 ieee80211_crypto_deinit();
309 return retval;
310 }
311
312 ieee80211_debug_level = debug;
313 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
314 if (ieee80211_proc == NULL) {
315 IEEE80211_ERROR("Unable to create " DRV_NAME
316 " proc directory\n");
317 return -EIO;
318 }
319 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
320 ieee80211_proc);
321 if (!e) {
322 remove_proc_entry(DRV_NAME, init_net.proc_net);
323 ieee80211_proc = NULL;
324 return -EIO;
325 }
326 e->read_proc = show_debug_level;
327 e->write_proc = store_debug_level;
328 e->data = NULL;
329
330 return 0;
331}
332
333void __exit ieee80211_rtl_exit(void)
334{
335 if (ieee80211_proc) {
336 remove_proc_entry("debug_level", ieee80211_proc);
337 remove_proc_entry(DRV_NAME, init_net.proc_net);
338 ieee80211_proc = NULL;
339 }
340 ieee80211_crypto_wep_exit();
341 ieee80211_crypto_ccmp_exit();
342 ieee80211_crypto_tkip_exit();
343 ieee80211_crypto_deinit();
344}
345
346#include <linux/moduleparam.h>
347module_param(debug, int, 0444);
348MODULE_PARM_DESC(debug, "debug output mask");
349
350
351#endif
352
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
new file mode 100644
index 00000000000..022086d2a3f
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -0,0 +1,2676 @@
1/*
2 * Original code based Host AP (software wireless LAN access point) driver
3 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2004, Intel Corporation
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. See README and COPYING for
13 * more details.
14 ******************************************************************************
15
16 Few modifications for Realtek's Wi-Fi drivers by
17 Andrea Merello <andreamrl@tiscali.it>
18
19 A special thanks goes to Realtek for their support !
20
21******************************************************************************/
22
23
24#include <linux/compiler.h>
25#include <linux/errno.h>
26#include <linux/if_arp.h>
27#include <linux/in6.h>
28#include <linux/in.h>
29#include <linux/ip.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/netdevice.h>
33#include <linux/pci.h>
34#include <linux/proc_fs.h>
35#include <linux/skbuff.h>
36#include <linux/slab.h>
37#include <linux/tcp.h>
38#include <linux/types.h>
39#include <linux/wireless.h>
40#include <linux/etherdevice.h>
41#include <asm/uaccess.h>
42#include <linux/ctype.h>
43
44#include "ieee80211.h"
45#ifdef ENABLE_DOT11D
46#include "dot11d.h"
47#endif
48static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
49 struct sk_buff *skb,
50 struct ieee80211_rx_stats *rx_stats)
51{
52 struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *)skb->data;
53 u16 fc = le16_to_cpu(hdr->frame_ctl);
54
55 skb->dev = ieee->dev;
56 skb_reset_mac_header(skb);
57
58 skb_pull(skb, ieee80211_get_hdrlen(fc));
59 skb->pkt_type = PACKET_OTHERHOST;
60 skb->protocol = __constant_htons(ETH_P_80211_RAW);
61 memset(skb->cb, 0, sizeof(skb->cb));
62 netif_rx(skb);
63}
64
65
66/* Called only as a tasklet (software IRQ) */
67static struct ieee80211_frag_entry *
68ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
69 unsigned int frag, u8 tid,u8 *src, u8 *dst)
70{
71 struct ieee80211_frag_entry *entry;
72 int i;
73
74 for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
75 entry = &ieee->frag_cache[tid][i];
76 if (entry->skb != NULL &&
77 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
78 IEEE80211_DEBUG_FRAG(
79 "expiring fragment cache entry "
80 "seq=%u last_frag=%u\n",
81 entry->seq, entry->last_frag);
82 dev_kfree_skb_any(entry->skb);
83 entry->skb = NULL;
84 }
85
86 if (entry->skb != NULL && entry->seq == seq &&
87 (entry->last_frag + 1 == frag || frag == -1) &&
88 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
89 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
90 return entry;
91 }
92
93 return NULL;
94}
95
96/* Called only as a tasklet (software IRQ) */
97static struct sk_buff *
98ieee80211_frag_cache_get(struct ieee80211_device *ieee,
99 struct ieee80211_hdr_4addr *hdr)
100{
101 struct sk_buff *skb = NULL;
102 u16 fc = le16_to_cpu(hdr->frame_ctl);
103 u16 sc = le16_to_cpu(hdr->seq_ctl);
104 unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
105 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
106 struct ieee80211_frag_entry *entry;
107 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
108 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
109 u8 tid;
110
111 if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
112 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
113 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
114 tid = UP2AC(tid);
115 tid ++;
116 } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
117 hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
118 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
119 tid = UP2AC(tid);
120 tid ++;
121 } else {
122 tid = 0;
123 }
124
125 if (frag == 0) {
126 /* Reserve enough space to fit maximum frame length */
127 skb = dev_alloc_skb(ieee->dev->mtu +
128 sizeof(struct ieee80211_hdr_4addr) +
129 8 /* LLC */ +
130 2 /* alignment */ +
131 8 /* WEP */ +
132 ETH_ALEN /* WDS */ +
133 (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
134 if (skb == NULL)
135 return NULL;
136
137 entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
138 ieee->frag_next_idx[tid]++;
139 if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
140 ieee->frag_next_idx[tid] = 0;
141
142 if (entry->skb != NULL)
143 dev_kfree_skb_any(entry->skb);
144
145 entry->first_frag_time = jiffies;
146 entry->seq = seq;
147 entry->last_frag = frag;
148 entry->skb = skb;
149 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
150 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
151 } else {
152 /* received a fragment of a frame for which the head fragment
153 * should have already been received */
154 entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
155 hdr->addr1);
156 if (entry != NULL) {
157 entry->last_frag = frag;
158 skb = entry->skb;
159 }
160 }
161
162 return skb;
163}
164
165
166/* Called only as a tasklet (software IRQ) */
167static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
168 struct ieee80211_hdr_4addr *hdr)
169{
170 u16 fc = le16_to_cpu(hdr->frame_ctl);
171 u16 sc = le16_to_cpu(hdr->seq_ctl);
172 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
173 struct ieee80211_frag_entry *entry;
174 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
175 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
176 u8 tid;
177
178 if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
179 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
180 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
181 tid = UP2AC(tid);
182 tid ++;
183 } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
184 hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
185 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
186 tid = UP2AC(tid);
187 tid ++;
188 } else {
189 tid = 0;
190 }
191
192 entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
193 hdr->addr1);
194
195 if (entry == NULL) {
196 IEEE80211_DEBUG_FRAG(
197 "could not invalidate fragment cache "
198 "entry (seq=%u)\n", seq);
199 return -1;
200 }
201
202 entry->skb = NULL;
203 return 0;
204}
205
206
207
208/* ieee80211_rx_frame_mgtmt
209 *
210 * Responsible for handling management control frames
211 *
212 * Called by ieee80211_rx */
213static inline int
214ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
215 struct ieee80211_rx_stats *rx_stats, u16 type,
216 u16 stype)
217{
218 /* On the struct stats definition there is written that
219 * this is not mandatory.... but seems that the probe
220 * response parser uses it
221 */
222 struct ieee80211_hdr_3addr * hdr = (struct ieee80211_hdr_3addr *)skb->data;
223
224 rx_stats->len = skb->len;
225 ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats);
226 if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames
227 {
228 dev_kfree_skb_any(skb);
229 return 0;
230 }
231
232 ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
233
234 dev_kfree_skb_any(skb);
235
236 return 0;
237
238 #ifdef NOT_YET
239 if (ieee->iw_mode == IW_MODE_MASTER) {
240 printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
241 ieee->dev->name);
242 return 0;
243 }
244
245 if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) {
246 if (stype == WLAN_FC_STYPE_BEACON &&
247 ieee->iw_mode == IW_MODE_MASTER) {
248 struct sk_buff *skb2;
249 /* Process beacon frames also in kernel driver to
250 * update STA(AP) table statistics */
251 skb2 = skb_clone(skb, GFP_ATOMIC);
252 if (skb2)
253 hostap_rx(skb2->dev, skb2, rx_stats);
254 }
255
256 /* send management frames to the user space daemon for
257 * processing */
258 ieee->apdevstats.rx_packets++;
259 ieee->apdevstats.rx_bytes += skb->len;
260 prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
261 return 0;
262 }
263
264 if (ieee->iw_mode == IW_MODE_MASTER) {
265 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
266 printk(KERN_DEBUG "%s: unknown management frame "
267 "(type=0x%02x, stype=0x%02x) dropped\n",
268 skb->dev->name, type, stype);
269 return -1;
270 }
271
272 hostap_rx(skb->dev, skb, rx_stats);
273 return 0;
274 }
275
276 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
277 "received in non-Host AP mode\n", skb->dev->name);
278 return -1;
279 #endif
280}
281
282
283
284/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
285/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
286static unsigned char rfc1042_header[] =
287{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
288/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
289static unsigned char bridge_tunnel_header[] =
290{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
291/* No encapsulation header if EtherType < 0x600 (=length) */
292
293/* Called by ieee80211_rx_frame_decrypt */
294static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
295 struct sk_buff *skb, size_t hdrlen)
296{
297 struct net_device *dev = ieee->dev;
298 u16 fc, ethertype;
299 struct ieee80211_hdr_4addr *hdr;
300 u8 *pos;
301
302 if (skb->len < 24)
303 return 0;
304
305 if (ieee->hwsec_active)
306 {
307 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
308 tcb_desc->bHwSec = 1;
309
310 if(ieee->need_sw_enc)
311 tcb_desc->bHwSec = 0;
312 }
313
314 hdr = (struct ieee80211_hdr_4addr *) skb->data;
315 fc = le16_to_cpu(hdr->frame_ctl);
316
317 /* check that the frame is unicast frame to us */
318 if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
319 IEEE80211_FCTL_TODS &&
320 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
321 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
322 /* ToDS frame with own addr BSSID and DA */
323 } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
324 IEEE80211_FCTL_FROMDS &&
325 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
326 /* FromDS frame with own addr as DA */
327 } else
328 return 0;
329
330 if (skb->len < 24 + 8)
331 return 0;
332
333 /* check for port access entity Ethernet type */
334 pos = skb->data + hdrlen;
335 ethertype = (pos[6] << 8) | pos[7];
336 if (ethertype == ETH_P_PAE)
337 return 1;
338
339 return 0;
340}
341
342/* Called only as a tasklet (software IRQ), by ieee80211_rx */
343static inline int
344ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
345 struct ieee80211_crypt_data *crypt)
346{
347 struct ieee80211_hdr_4addr *hdr;
348 int res, hdrlen;
349
350 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
351 return 0;
352
353 if (ieee->hwsec_active)
354 {
355 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
356 tcb_desc->bHwSec = 1;
357 }
358
359 hdr = (struct ieee80211_hdr_4addr *) skb->data;
360 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
361
362#ifdef CONFIG_IEEE80211_CRYPT_TKIP
363 if (ieee->tkip_countermeasures &&
364 strcmp(crypt->ops->name, "TKIP") == 0) {
365 if (net_ratelimit()) {
366 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
367 "received packet from %pM\n",
368 ieee->dev->name, hdr->addr2);
369 }
370 return -1;
371 }
372#endif
373
374 atomic_inc(&crypt->refcnt);
375 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
376 atomic_dec(&crypt->refcnt);
377 if (res < 0) {
378 IEEE80211_DEBUG_DROP(
379 "decryption failed (SA=%pM"
380 ") res=%d\n", hdr->addr2, res);
381 if (res == -2)
382 IEEE80211_DEBUG_DROP("Decryption failed ICV "
383 "mismatch (key %d)\n",
384 skb->data[hdrlen + 3] >> 6);
385 ieee->ieee_stats.rx_discards_undecryptable++;
386 return -1;
387 }
388
389 return res;
390}
391
392
393/* Called only as a tasklet (software IRQ), by ieee80211_rx */
394static inline int
395ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
396 int keyidx, struct ieee80211_crypt_data *crypt)
397{
398 struct ieee80211_hdr_4addr *hdr;
399 int res, hdrlen;
400
401 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
402 return 0;
403 if (ieee->hwsec_active)
404 {
405 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
406 tcb_desc->bHwSec = 1;
407
408 if(ieee->need_sw_enc)
409 tcb_desc->bHwSec = 0;
410
411 }
412
413 hdr = (struct ieee80211_hdr_4addr *) skb->data;
414 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
415
416 atomic_inc(&crypt->refcnt);
417 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
418 atomic_dec(&crypt->refcnt);
419 if (res < 0) {
420 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
421 " (SA=%pM keyidx=%d)\n",
422 ieee->dev->name, hdr->addr2, keyidx);
423 return -1;
424 }
425
426 return 0;
427}
428
429
430/* this function is stolen from ipw2200 driver*/
431#define IEEE_PACKET_RETRY_TIME (5*HZ)
432static int is_duplicate_packet(struct ieee80211_device *ieee,
433 struct ieee80211_hdr_4addr *header)
434{
435 u16 fc = le16_to_cpu(header->frame_ctl);
436 u16 sc = le16_to_cpu(header->seq_ctl);
437 u16 seq = WLAN_GET_SEQ_SEQ(sc);
438 u16 frag = WLAN_GET_SEQ_FRAG(sc);
439 u16 *last_seq, *last_frag;
440 unsigned long *last_time;
441 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
442 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
443 u8 tid;
444
445
446 //TO2DS and QoS
447 if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
448 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
449 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
450 tid = UP2AC(tid);
451 tid ++;
452 } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
453 hdr_3addrqos = (struct ieee80211_hdr_3addrqos*)header;
454 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
455 tid = UP2AC(tid);
456 tid ++;
457 } else { // no QoS
458 tid = 0;
459 }
460
461 switch (ieee->iw_mode) {
462 case IW_MODE_ADHOC:
463 {
464 struct list_head *p;
465 struct ieee_ibss_seq *entry = NULL;
466 u8 *mac = header->addr2;
467 int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
468
469 list_for_each(p, &ieee->ibss_mac_hash[index]) {
470 entry = list_entry(p, struct ieee_ibss_seq, list);
471 if (!memcmp(entry->mac, mac, ETH_ALEN))
472 break;
473 }
474
475 if (p == &ieee->ibss_mac_hash[index]) {
476 entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
477 if (!entry) {
478 printk(KERN_WARNING "Cannot malloc new mac entry\n");
479 return 0;
480 }
481 memcpy(entry->mac, mac, ETH_ALEN);
482 entry->seq_num[tid] = seq;
483 entry->frag_num[tid] = frag;
484 entry->packet_time[tid] = jiffies;
485 list_add(&entry->list, &ieee->ibss_mac_hash[index]);
486 return 0;
487 }
488 last_seq = &entry->seq_num[tid];
489 last_frag = &entry->frag_num[tid];
490 last_time = &entry->packet_time[tid];
491 break;
492 }
493
494 case IW_MODE_INFRA:
495 last_seq = &ieee->last_rxseq_num[tid];
496 last_frag = &ieee->last_rxfrag_num[tid];
497 last_time = &ieee->last_packet_time[tid];
498
499 break;
500 default:
501 return 0;
502 }
503
504 if ((*last_seq == seq) &&
505 time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
506 if (*last_frag == frag){
507 goto drop;
508
509 }
510 if (*last_frag + 1 != frag)
511 /* out-of-order fragment */
512 goto drop;
513 } else
514 *last_seq = seq;
515
516 *last_frag = frag;
517 *last_time = jiffies;
518 return 0;
519
520drop:
521 return 1;
522}
523bool
524AddReorderEntry(
525 PRX_TS_RECORD pTS,
526 PRX_REORDER_ENTRY pReorderEntry
527 )
528{
529 struct list_head *pList = &pTS->RxPendingPktList;
530
531 while(pList->next != &pTS->RxPendingPktList)
532 {
533 if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
534 {
535 pList = pList->next;
536 }
537 else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
538 {
539 return false;
540 }
541 else
542 {
543 break;
544 }
545 }
546
547 pReorderEntry->List.next = pList->next;
548 pReorderEntry->List.next->prev = &pReorderEntry->List;
549 pReorderEntry->List.prev = pList;
550 pList->next = &pReorderEntry->List;
551
552 return true;
553}
554
555void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index)
556{
557 u8 i = 0 , j=0;
558 u16 ethertype;
559
560 for(j = 0; j<index; j++)
561 {
562//added by amy for reorder
563 struct ieee80211_rxb* prxb = prxbIndicateArray[j];
564 for(i = 0; i<prxb->nr_subframes; i++) {
565 struct sk_buff *sub_skb = prxb->subframes[i];
566
567 /* convert hdr + possible LLC headers into Ethernet header */
568 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
569 if (sub_skb->len >= 8 &&
570 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
571 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
572 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
573 /* remove RFC1042 or Bridge-Tunnel encapsulation and
574 * replace EtherType */
575 skb_pull(sub_skb, SNAP_SIZE);
576 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
577 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
578 } else {
579 u16 len;
580 /* Leave Ethernet header part of hdr and full payload */
581 len = htons(sub_skb->len);
582 memcpy(skb_push(sub_skb, 2), &len, 2);
583 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
584 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
585 }
586
587 /* Indicat the packets to upper layer */
588 if (sub_skb) {
589 sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
590 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
591 sub_skb->dev = ieee->dev;
592 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
593 ieee->last_rx_ps_time = jiffies;
594 netif_rx(sub_skb);
595 }
596 }
597 kfree(prxb);
598 prxb = NULL;
599 }
600}
601
602
603void RxReorderIndicatePacket( struct ieee80211_device *ieee,
604 struct ieee80211_rxb* prxb,
605 PRX_TS_RECORD pTS,
606 u16 SeqNum)
607{
608 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
609 PRX_REORDER_ENTRY pReorderEntry = NULL;
610 struct ieee80211_rxb* prxbIndicateArray[REORDER_WIN_SIZE];
611 u8 WinSize = pHTInfo->RxReorderWinSize;
612 u16 WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;
613 u8 index = 0;
614 bool bMatchWinStart = false, bPktInBuf = false;
615 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize);
616
617 /* Rx Reorder initialize condition.*/
618 if(pTS->RxIndicateSeq == 0xffff) {
619 pTS->RxIndicateSeq = SeqNum;
620 }
621
622 /* Drop out the packet which SeqNum is smaller than WinStart */
623 if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
624 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
625 pTS->RxIndicateSeq, SeqNum);
626 pHTInfo->RxReorderDropCounter++;
627 {
628 int i;
629 for(i =0; i < prxb->nr_subframes; i++) {
630 dev_kfree_skb(prxb->subframes[i]);
631 }
632 kfree(prxb);
633 prxb = NULL;
634 }
635 return;
636 }
637
638 /*
639 * Sliding window manipulation. Conditions includes:
640 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
641 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
642 */
643 if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
644 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
645 bMatchWinStart = true;
646 } else if(SN_LESS(WinEnd, SeqNum)) {
647 if(SeqNum >= (WinSize - 1)) {
648 pTS->RxIndicateSeq = SeqNum + 1 -WinSize;
649 } else {
650 pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1;
651 }
652 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
653 }
654
655 /*
656 * Indication process.
657 * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
658 * with the SeqNum smaller than latest WinStart and buffer other packets.
659 */
660 /* For Rx Reorder condition:
661 * 1. All packets with SeqNum smaller than WinStart => Indicate
662 * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
663 */
664 if(bMatchWinStart) {
665 /* Current packet is going to be indicated.*/
666 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
667 pTS->RxIndicateSeq, SeqNum);
668 prxbIndicateArray[0] = prxb;
669 index = 1;
670 } else {
671 /* Current packet is going to be inserted into pending list.*/
672 if(!list_empty(&ieee->RxReorder_Unused_List)) {
673 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
674 list_del_init(&pReorderEntry->List);
675
676 /* Make a reorder entry and insert into a the packet list.*/
677 pReorderEntry->SeqNum = SeqNum;
678 pReorderEntry->prxb = prxb;
679
680 if(!AddReorderEntry(pTS, pReorderEntry)) {
681 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
682 __FUNCTION__, pTS->RxIndicateSeq, SeqNum);
683 list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
684 {
685 int i;
686 for(i =0; i < prxb->nr_subframes; i++) {
687 dev_kfree_skb(prxb->subframes[i]);
688 }
689 kfree(prxb);
690 prxb = NULL;
691 }
692 } else {
693 IEEE80211_DEBUG(IEEE80211_DL_REORDER,
694 "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
695 }
696 }
697 else {
698 /*
699 * Packets are dropped if there is not enough reorder entries.
700 * This part shall be modified!! We can just indicate all the
701 * packets in buffer and get reorder entries.
702 */
703 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
704 {
705 int i;
706 for(i =0; i < prxb->nr_subframes; i++) {
707 dev_kfree_skb(prxb->subframes[i]);
708 }
709 kfree(prxb);
710 prxb = NULL;
711 }
712 }
713 }
714
715 /* Check if there is any packet need indicate.*/
716 while(!list_empty(&pTS->RxPendingPktList)) {
717 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__);
718#if 1
719 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
720 if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
721 SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
722 {
723 /* This protect buffer from overflow. */
724 if(index >= REORDER_WIN_SIZE) {
725 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n");
726 bPktInBuf = true;
727 break;
728 }
729
730 list_del_init(&pReorderEntry->List);
731
732 if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
733 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
734
735 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
736 prxbIndicateArray[index] = pReorderEntry->prxb;
737 index++;
738
739 list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
740 } else {
741 bPktInBuf = true;
742 break;
743 }
744#endif
745 }
746
747 /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
748 if(index>0) {
749 // Cancel previous pending timer.
750 if (timer_pending(&pTS->RxPktPendingTimer))
751 del_timer_sync(&pTS->RxPktPendingTimer);
752 pTS->RxTimeoutIndicateSeq = 0xffff;
753
754 // Indicate packets
755 if(index>REORDER_WIN_SIZE){
756 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
757 return;
758 }
759 ieee80211_indicate_packets(ieee, prxbIndicateArray, index);
760 bPktInBuf = false;
761 }
762
763 if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
764 // Set new pending timer.
765 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__);
766 pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
767
768 mod_timer(&pTS->RxPktPendingTimer, jiffies + MSECS(pHTInfo->RxReorderPendingTime));
769 }
770}
771
772u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
773 struct ieee80211_rx_stats *rx_stats,
774 struct ieee80211_rxb *rxb,u8* src,u8* dst)
775{
776 struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data;
777 u16 fc = le16_to_cpu(hdr->frame_ctl);
778
779 u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr);
780 u16 ChkLength;
781 bool bIsAggregateFrame = false;
782 u16 nSubframe_Length;
783 u8 nPadding_Length = 0;
784 u16 SeqNum=0;
785
786 struct sk_buff *sub_skb;
787 u8 *data_ptr;
788 /* just for debug purpose */
789 SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
790
791 if((IEEE80211_QOS_HAS_SEQ(fc))&&\
792 (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
793 bIsAggregateFrame = true;
794 }
795
796 if(IEEE80211_QOS_HAS_SEQ(fc)) {
797 LLCOffset += 2;
798 }
799
800 if(rx_stats->bContainHTC) {
801 LLCOffset += sHTCLng;
802 }
803 // Null packet, don't indicate it to upper layer
804 ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
805
806 if( skb->len <= ChkLength ) {
807 return 0;
808 }
809
810 skb_pull(skb, LLCOffset);
811 ieee->bIsAggregateFrame = bIsAggregateFrame;//added by amy for Leisure PS
812
813 if(!bIsAggregateFrame) {
814 rxb->nr_subframes = 1;
815#ifdef JOHN_NOCPY
816 rxb->subframes[0] = skb;
817#else
818 rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC);
819#endif
820
821 memcpy(rxb->src,src,ETH_ALEN);
822 memcpy(rxb->dst,dst,ETH_ALEN);
823 //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len);
824 return 1;
825 } else {
826 rxb->nr_subframes = 0;
827 memcpy(rxb->src,src,ETH_ALEN);
828 memcpy(rxb->dst,dst,ETH_ALEN);
829 while(skb->len > ETHERNET_HEADER_SIZE) {
830 /* Offset 12 denote 2 mac address */
831 nSubframe_Length = *((u16*)(skb->data + 12));
832 //==m==>change the length order
833 nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
834
835 if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
836 printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
837 __FUNCTION__,rxb->nr_subframes);
838 printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length);
839 printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length);
840 printk("The Packet SeqNum is %d\n",SeqNum);
841 return 0;
842 }
843
844 /* move the data point to data content */
845 skb_pull(skb, ETHERNET_HEADER_SIZE);
846
847#ifdef JOHN_NOCPY
848 sub_skb = skb_clone(skb, GFP_ATOMIC);
849 sub_skb->len = nSubframe_Length;
850 sub_skb->tail = sub_skb->data + nSubframe_Length;
851#else
852 /* Allocate new skb for releasing to upper layer */
853 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
854 skb_reserve(sub_skb, 12);
855 data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
856 memcpy(data_ptr,skb->data,nSubframe_Length);
857#endif
858 rxb->subframes[rxb->nr_subframes++] = sub_skb;
859 if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
860 IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
861 break;
862 }
863 skb_pull(skb,nSubframe_Length);
864
865 if(skb->len != 0) {
866 nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4);
867 if(nPadding_Length == 4) {
868 nPadding_Length = 0;
869 }
870
871 if(skb->len < nPadding_Length) {
872 return 0;
873 }
874
875 skb_pull(skb,nPadding_Length);
876 }
877 }
878#ifdef JOHN_NOCPY
879 dev_kfree_skb(skb);
880#endif
881 return rxb->nr_subframes;
882 }
883}
884
885/* All received frames are sent to this function. @skb contains the frame in
886 * IEEE 802.11 format, i.e., in the format it was sent over air.
887 * This function is called only as a tasklet (software IRQ). */
888int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
889 struct ieee80211_rx_stats *rx_stats)
890{
891 struct net_device *dev = ieee->dev;
892 struct ieee80211_hdr_4addr *hdr;
893
894 size_t hdrlen;
895 u16 fc, type, stype, sc;
896 struct net_device_stats *stats;
897 unsigned int frag;
898 u8 *payload;
899 u16 ethertype;
900 //added by amy for reorder
901 u8 TID = 0;
902 u16 SeqNum = 0;
903 PRX_TS_RECORD pTS = NULL;
904 bool unicast_packet = false;
905 //added by amy for reorder
906#ifdef NOT_YET
907 struct net_device *wds = NULL;
908 struct sk_buff *skb2 = NULL;
909 struct net_device *wds = NULL;
910 int frame_authorized = 0;
911 int from_assoc_ap = 0;
912 void *sta = NULL;
913#endif
914 u8 dst[ETH_ALEN];
915 u8 src[ETH_ALEN];
916 u8 bssid[ETH_ALEN];
917 struct ieee80211_crypt_data *crypt = NULL;
918 int keyidx = 0;
919
920 int i;
921 struct ieee80211_rxb* rxb = NULL;
922 // cheat the the hdr type
923 hdr = (struct ieee80211_hdr_4addr *)skb->data;
924 stats = &ieee->stats;
925
926 if (skb->len < 10) {
927 printk(KERN_INFO "%s: SKB length < 10\n",
928 dev->name);
929 goto rx_dropped;
930 }
931
932 fc = le16_to_cpu(hdr->frame_ctl);
933 type = WLAN_FC_GET_TYPE(fc);
934 stype = WLAN_FC_GET_STYPE(fc);
935 sc = le16_to_cpu(hdr->seq_ctl);
936
937 frag = WLAN_GET_SEQ_FRAG(sc);
938 hdrlen = ieee80211_get_hdrlen(fc);
939
940 if(HTCCheck(ieee, skb->data))
941 {
942 if(net_ratelimit())
943 printk("find HTCControl\n");
944 hdrlen += 4;
945 rx_stats->bContainHTC = 1;
946 }
947
948#ifdef NOT_YET
949#if WIRELESS_EXT > 15
950 /* Put this code here so that we avoid duplicating it in all
951 * Rx paths. - Jean II */
952#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
953 /* If spy monitoring on */
954 if (iface->spy_data.spy_number > 0) {
955 struct iw_quality wstats;
956 wstats.level = rx_stats->rssi;
957 wstats.noise = rx_stats->noise;
958 wstats.updated = 6; /* No qual value */
959 /* Update spy records */
960 wireless_spy_update(dev, hdr->addr2, &wstats);
961 }
962#endif /* IW_WIRELESS_SPY */
963#endif /* WIRELESS_EXT > 15 */
964 hostap_update_rx_stats(local->ap, hdr, rx_stats);
965#endif
966
967#if WIRELESS_EXT > 15
968 if (ieee->iw_mode == IW_MODE_MONITOR) {
969 ieee80211_monitor_rx(ieee, skb, rx_stats);
970 stats->rx_packets++;
971 stats->rx_bytes += skb->len;
972 return 1;
973 }
974#endif
975 if (ieee->host_decrypt) {
976 int idx = 0;
977 if (skb->len >= hdrlen + 3)
978 idx = skb->data[hdrlen + 3] >> 6;
979 crypt = ieee->crypt[idx];
980#ifdef NOT_YET
981 sta = NULL;
982
983 /* Use station specific key to override default keys if the
984 * receiver address is a unicast address ("individual RA"). If
985 * bcrx_sta_key parameter is set, station specific key is used
986 * even with broad/multicast targets (this is against IEEE
987 * 802.11, but makes it easier to use different keys with
988 * stations that do not support WEP key mapping). */
989
990 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
991 (void) hostap_handle_sta_crypto(local, hdr, &crypt,
992 &sta);
993#endif
994
995 /* allow NULL decrypt to indicate an station specific override
996 * for default encryption */
997 if (crypt && (crypt->ops == NULL ||
998 crypt->ops->decrypt_mpdu == NULL))
999 crypt = NULL;
1000
1001 if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
1002 /* This seems to be triggered by some (multicast?)
1003 * frames from other than current BSS, so just drop the
1004 * frames silently instead of filling system log with
1005 * these reports. */
1006 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
1007 " (SA=%pM)\n",
1008 hdr->addr2);
1009 ieee->ieee_stats.rx_discards_undecryptable++;
1010 goto rx_dropped;
1011 }
1012 }
1013
1014 if (skb->len < IEEE80211_DATA_HDR3_LEN)
1015 goto rx_dropped;
1016
1017 // if QoS enabled, should check the sequence for each of the AC
1018 if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){
1019 if (is_duplicate_packet(ieee, hdr))
1020 goto rx_dropped;
1021
1022 }
1023 else
1024 {
1025 PRX_TS_RECORD pRxTS = NULL;
1026
1027 if(GetTs(
1028 ieee,
1029 (PTS_COMMON_INFO*) &pRxTS,
1030 hdr->addr2,
1031 (u8)Frame_QoSTID((u8*)(skb->data)),
1032 RX_DIR,
1033 true))
1034 {
1035
1036 if( (fc & (1<<11)) &&
1037 (frag == pRxTS->RxLastFragNum) &&
1038 (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum) )
1039 {
1040 goto rx_dropped;
1041 }
1042 else
1043 {
1044 pRxTS->RxLastFragNum = frag;
1045 pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
1046 }
1047 }
1048 else
1049 {
1050 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__FUNCTION__);
1051 goto rx_dropped;
1052 }
1053 }
1054
1055 if (type == IEEE80211_FTYPE_MGMT) {
1056
1057 if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
1058 goto rx_dropped;
1059 else
1060 goto rx_exit;
1061 }
1062
1063 /* Data frame - extract src/dst addresses */
1064 switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
1065 case IEEE80211_FCTL_FROMDS:
1066 memcpy(dst, hdr->addr1, ETH_ALEN);
1067 memcpy(src, hdr->addr3, ETH_ALEN);
1068 memcpy(bssid, hdr->addr2, ETH_ALEN);
1069 break;
1070 case IEEE80211_FCTL_TODS:
1071 memcpy(dst, hdr->addr3, ETH_ALEN);
1072 memcpy(src, hdr->addr2, ETH_ALEN);
1073 memcpy(bssid, hdr->addr1, ETH_ALEN);
1074 break;
1075 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
1076 if (skb->len < IEEE80211_DATA_HDR4_LEN)
1077 goto rx_dropped;
1078 memcpy(dst, hdr->addr3, ETH_ALEN);
1079 memcpy(src, hdr->addr4, ETH_ALEN);
1080 memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
1081 break;
1082 case 0:
1083 memcpy(dst, hdr->addr1, ETH_ALEN);
1084 memcpy(src, hdr->addr2, ETH_ALEN);
1085 memcpy(bssid, hdr->addr3, ETH_ALEN);
1086 break;
1087 }
1088
1089#ifdef NOT_YET
1090 if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
1091 goto rx_dropped;
1092 if (wds) {
1093 skb->dev = dev = wds;
1094 stats = hostap_get_stats(dev);
1095 }
1096
1097 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
1098 (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS &&
1099 ieee->stadev &&
1100 memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
1101 /* Frame from BSSID of the AP for which we are a client */
1102 skb->dev = dev = ieee->stadev;
1103 stats = hostap_get_stats(dev);
1104 from_assoc_ap = 1;
1105 }
1106#endif
1107
1108 dev->last_rx = jiffies;
1109
1110#ifdef NOT_YET
1111 if ((ieee->iw_mode == IW_MODE_MASTER ||
1112 ieee->iw_mode == IW_MODE_REPEAT) &&
1113 !from_assoc_ap) {
1114 switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
1115 wds != NULL)) {
1116 case AP_RX_CONTINUE_NOT_AUTHORIZED:
1117 frame_authorized = 0;
1118 break;
1119 case AP_RX_CONTINUE:
1120 frame_authorized = 1;
1121 break;
1122 case AP_RX_DROP:
1123 goto rx_dropped;
1124 case AP_RX_EXIT:
1125 goto rx_exit;
1126 }
1127 }
1128#endif
1129 /* Nullfunc frames may have PS-bit set, so they must be passed to
1130 * hostap_handle_sta_rx() before being dropped here. */
1131 if (stype != IEEE80211_STYPE_DATA &&
1132 stype != IEEE80211_STYPE_DATA_CFACK &&
1133 stype != IEEE80211_STYPE_DATA_CFPOLL &&
1134 stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
1135 stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
1136 ) {
1137 if (stype != IEEE80211_STYPE_NULLFUNC)
1138 IEEE80211_DEBUG_DROP(
1139 "RX: dropped data frame "
1140 "with no data (type=0x%02x, "
1141 "subtype=0x%02x, len=%d)\n",
1142 type, stype, skb->len);
1143 goto rx_dropped;
1144 }
1145 if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
1146 goto rx_dropped;
1147
1148#ifdef ENABLE_LPS
1149 if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == 1)
1150 && (ieee->polling)) {
1151 if (WLAN_FC_MORE_DATA(fc)) {
1152 /* more data bit is set, let's request a new frame from the AP */
1153 ieee80211_sta_ps_send_pspoll_frame(ieee);
1154 } else {
1155 ieee->polling = false;
1156 }
1157 }
1158#endif
1159
1160 ieee->need_sw_enc = 0;
1161
1162 if((!rx_stats->Decrypted)){
1163 ieee->need_sw_enc = 1;
1164 }
1165
1166 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
1167
1168 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1169 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
1170 {
1171 printk("decrypt frame error\n");
1172 goto rx_dropped;
1173 }
1174
1175
1176 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1177
1178 /* skb: hdr + (possibly fragmented) plaintext payload */
1179 // PR: FIXME: hostap has additional conditions in the "if" below:
1180 // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1181 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
1182 int flen;
1183 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
1184 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
1185
1186 if (!frag_skb) {
1187 IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
1188 "Rx cannot get skb from fragment "
1189 "cache (morefrag=%d seq=%u frag=%u)\n",
1190 (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
1191 WLAN_GET_SEQ_SEQ(sc), frag);
1192 goto rx_dropped;
1193 }
1194 flen = skb->len;
1195 if (frag != 0)
1196 flen -= hdrlen;
1197
1198 if (frag_skb->tail + flen > frag_skb->end) {
1199 printk(KERN_WARNING "%s: host decrypted and "
1200 "reassembled frame did not fit skb\n",
1201 dev->name);
1202 ieee80211_frag_cache_invalidate(ieee, hdr);
1203 goto rx_dropped;
1204 }
1205
1206 if (frag == 0) {
1207 /* copy first fragment (including full headers) into
1208 * beginning of the fragment cache skb */
1209 memcpy(skb_put(frag_skb, flen), skb->data, flen);
1210 } else {
1211 /* append frame payload to the end of the fragment
1212 * cache skb */
1213 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
1214 flen);
1215 }
1216 dev_kfree_skb_any(skb);
1217 skb = NULL;
1218
1219 if (fc & IEEE80211_FCTL_MOREFRAGS) {
1220 /* more fragments expected - leave the skb in fragment
1221 * cache for now; it will be delivered to upper layers
1222 * after all fragments have been received */
1223 goto rx_exit;
1224 }
1225
1226 /* this was the last fragment and the frame will be
1227 * delivered, so remove skb from fragment cache */
1228 skb = frag_skb;
1229 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1230 ieee80211_frag_cache_invalidate(ieee, hdr);
1231 }
1232
1233 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
1234 * encrypted/authenticated */
1235 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1236 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
1237 {
1238 printk("==>decrypt msdu error\n");
1239 goto rx_dropped;
1240 }
1241
1242 //added by amy for AP roaming
1243 ieee->LinkDetectInfo.NumRecvDataInPeriod++;
1244 ieee->LinkDetectInfo.NumRxOkInPeriod++;
1245
1246 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1247 if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
1248 unicast_packet = true;
1249
1250 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
1251 if (/*ieee->ieee802_1x &&*/
1252 ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1253
1254#ifdef CONFIG_IEEE80211_DEBUG
1255 /* pass unencrypted EAPOL frames even if encryption is
1256 * configured */
1257 struct eapol *eap = (struct eapol *)(skb->data +
1258 24);
1259 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1260 eap_get_type(eap->type));
1261#endif
1262 } else {
1263 IEEE80211_DEBUG_DROP(
1264 "encryption configured, but RX "
1265 "frame not encrypted (SA=%pM)\n",
1266 hdr->addr2);
1267 goto rx_dropped;
1268 }
1269 }
1270
1271#ifdef CONFIG_IEEE80211_DEBUG
1272 if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
1273 ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1274 struct eapol *eap = (struct eapol *)(skb->data +
1275 24);
1276 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1277 eap_get_type(eap->type));
1278 }
1279#endif
1280
1281 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
1282 !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1283 IEEE80211_DEBUG_DROP(
1284 "dropped unencrypted RX data "
1285 "frame from %pM"
1286 " (drop_unencrypted=1)\n",
1287 hdr->addr2);
1288 goto rx_dropped;
1289 }
1290//added by amy for reorder
1291 if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
1292 && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
1293 {
1294 TID = Frame_QoSTID(skb->data);
1295 SeqNum = WLAN_GET_SEQ_SEQ(sc);
1296 GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
1297 if(TID !=0 && TID !=3)
1298 {
1299 ieee->bis_any_nonbepkts = true;
1300 }
1301 }
1302
1303//added by amy for reorder
1304 /* skb: hdr + (possible reassembled) full plaintext payload */
1305 payload = skb->data + hdrlen;
1306
1307 rxb = kmalloc(sizeof(struct ieee80211_rxb), GFP_ATOMIC);
1308 if(rxb == NULL)
1309 {
1310 IEEE80211_DEBUG(IEEE80211_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__);
1311 goto rx_dropped;
1312 }
1313 /* to parse amsdu packets */
1314 /* qos data packets & reserved bit is 1 */
1315 if(parse_subframe(ieee, skb,rx_stats,rxb,src,dst) == 0) {
1316 /* only to free rxb, and not submit the packets to upper layer */
1317 for(i =0; i < rxb->nr_subframes; i++) {
1318 dev_kfree_skb(rxb->subframes[i]);
1319 }
1320 kfree(rxb);
1321 rxb = NULL;
1322 goto rx_dropped;
1323 }
1324
1325#ifdef ENABLE_LPS
1326 if(unicast_packet)
1327 {
1328 if (type == IEEE80211_FTYPE_DATA)
1329 {
1330
1331 if(ieee->bIsAggregateFrame)
1332 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
1333 else
1334 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
1335
1336 // 2009.03.03 Leave DC mode immediately when detect high traffic
1337 if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
1338 {
1339 if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
1340 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
1341 {
1342 if(ieee->LeisurePSLeave)
1343 ieee->LeisurePSLeave(ieee);
1344 }
1345 }
1346 }
1347 }
1348#endif
1349
1350 ieee->last_rx_ps_time = jiffies;
1351//added by amy for reorder
1352 if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
1353//added by amy for reorder
1354 for(i = 0; i<rxb->nr_subframes; i++) {
1355 struct sk_buff *sub_skb = rxb->subframes[i];
1356
1357 if (sub_skb) {
1358 /* convert hdr + possible LLC headers into Ethernet header */
1359 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
1360 if (sub_skb->len >= 8 &&
1361 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
1362 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1363 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
1364 /* remove RFC1042 or Bridge-Tunnel encapsulation and
1365 * replace EtherType */
1366 skb_pull(sub_skb, SNAP_SIZE);
1367 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1368 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1369 } else {
1370 u16 len;
1371 /* Leave Ethernet header part of hdr and full payload */
1372 len = htons(sub_skb->len);
1373 memcpy(skb_push(sub_skb, 2), &len, 2);
1374 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1375 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1376 }
1377
1378 stats->rx_packets++;
1379 stats->rx_bytes += sub_skb->len;
1380 if(is_multicast_ether_addr(dst)) {
1381 stats->multicast++;
1382 }
1383
1384 /* Indicat the packets to upper layer */
1385 sub_skb->protocol = eth_type_trans(sub_skb, dev);
1386 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
1387 sub_skb->dev = dev;
1388 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
1389 netif_rx(sub_skb);
1390 }
1391 }
1392 kfree(rxb);
1393 rxb = NULL;
1394
1395 }
1396 else
1397 {
1398 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__);
1399 RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
1400 }
1401#ifndef JOHN_NOCPY
1402 dev_kfree_skb(skb);
1403#endif
1404
1405 rx_exit:
1406#ifdef NOT_YET
1407 if (sta)
1408 hostap_handle_sta_release(sta);
1409#endif
1410 return 1;
1411
1412 rx_dropped:
1413 kfree(rxb);
1414 rxb = NULL;
1415 stats->rx_dropped++;
1416
1417 /* Returning 0 indicates to caller that we have not handled the SKB--
1418 * so it is still allocated and can be used again by underlying
1419 * hardware as a DMA target */
1420 return 0;
1421}
1422
1423#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
1424
1425static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
1426
1427/*
1428* Make the structure we read from the beacon packet to have
1429* the right values
1430*/
1431static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
1432 *info_element, int sub_type)
1433{
1434
1435 if (info_element->qui_subtype != sub_type)
1436 return -1;
1437 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
1438 return -1;
1439 if (info_element->qui_type != QOS_OUI_TYPE)
1440 return -1;
1441 if (info_element->version != QOS_VERSION_1)
1442 return -1;
1443
1444 return 0;
1445}
1446
1447
1448/*
1449 * Parse a QoS parameter element
1450 */
1451static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
1452 *element_param, struct ieee80211_info_element
1453 *info_element)
1454{
1455 int ret = 0;
1456 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
1457
1458 if ((info_element == NULL) || (element_param == NULL))
1459 return -1;
1460
1461 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
1462 memcpy(element_param->info_element.qui, info_element->data,
1463 info_element->len);
1464 element_param->info_element.elementID = info_element->id;
1465 element_param->info_element.length = info_element->len;
1466 } else
1467 ret = -1;
1468 if (ret == 0)
1469 ret = ieee80211_verify_qos_info(&element_param->info_element,
1470 QOS_OUI_PARAM_SUB_TYPE);
1471 return ret;
1472}
1473
1474/*
1475 * Parse a QoS information element
1476 */
1477static int ieee80211_read_qos_info_element(struct
1478 ieee80211_qos_information_element
1479 *element_info, struct ieee80211_info_element
1480 *info_element)
1481{
1482 int ret = 0;
1483 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
1484
1485 if (element_info == NULL)
1486 return -1;
1487 if (info_element == NULL)
1488 return -1;
1489
1490 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1491 memcpy(element_info->qui, info_element->data,
1492 info_element->len);
1493 element_info->elementID = info_element->id;
1494 element_info->length = info_element->len;
1495 } else
1496 ret = -1;
1497
1498 if (ret == 0)
1499 ret = ieee80211_verify_qos_info(element_info,
1500 QOS_OUI_INFO_SUB_TYPE);
1501 return ret;
1502}
1503
1504
1505/*
1506 * Write QoS parameters from the ac parameters.
1507 */
1508static int ieee80211_qos_convert_ac_to_parameters(struct
1509 ieee80211_qos_parameter_info
1510 *param_elm, struct
1511 ieee80211_qos_parameters
1512 *qos_param)
1513{
1514 int rc = 0;
1515 int i;
1516 struct ieee80211_qos_ac_parameter *ac_params;
1517 u8 aci;
1518
1519 for (i = 0; i < QOS_QUEUE_NUM; i++) {
1520 ac_params = &(param_elm->ac_params_record[i]);
1521
1522 aci = (ac_params->aci_aifsn & 0x60) >> 5;
1523
1524 if(aci >= QOS_QUEUE_NUM)
1525 continue;
1526 qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
1527
1528 /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
1529 qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci];
1530
1531 qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F;
1532
1533 qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4;
1534
1535 qos_param->flag[aci] =
1536 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
1537 qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit);
1538 }
1539 return rc;
1540}
1541
1542/*
1543 * we have a generic data element which it may contain QoS information or
1544 * parameters element. check the information element length to decide
1545 * which type to read
1546 */
1547static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
1548 *info_element,
1549 struct ieee80211_network *network)
1550{
1551 int rc = 0;
1552 struct ieee80211_qos_parameters *qos_param = NULL;
1553 struct ieee80211_qos_information_element qos_info_element;
1554
1555 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
1556
1557 if (rc == 0) {
1558 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1559 network->flags |= NETWORK_HAS_QOS_INFORMATION;
1560 } else {
1561 struct ieee80211_qos_parameter_info param_element;
1562
1563 rc = ieee80211_read_qos_param_element(&param_element,
1564 info_element);
1565 if (rc == 0) {
1566 qos_param = &(network->qos_data.parameters);
1567 ieee80211_qos_convert_ac_to_parameters(&param_element,
1568 qos_param);
1569 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1570 network->qos_data.param_count =
1571 param_element.info_element.ac_info & 0x0F;
1572 }
1573 }
1574
1575 if (rc == 0) {
1576 IEEE80211_DEBUG_QOS("QoS is supported\n");
1577 network->qos_data.supported = 1;
1578 }
1579 return rc;
1580}
1581
1582#ifdef CONFIG_IEEE80211_DEBUG
1583#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1584
1585static const char *get_info_element_string(u16 id)
1586{
1587 switch (id) {
1588 MFIE_STRING(SSID);
1589 MFIE_STRING(RATES);
1590 MFIE_STRING(FH_SET);
1591 MFIE_STRING(DS_SET);
1592 MFIE_STRING(CF_SET);
1593 MFIE_STRING(TIM);
1594 MFIE_STRING(IBSS_SET);
1595 MFIE_STRING(COUNTRY);
1596 MFIE_STRING(HOP_PARAMS);
1597 MFIE_STRING(HOP_TABLE);
1598 MFIE_STRING(REQUEST);
1599 MFIE_STRING(CHALLENGE);
1600 MFIE_STRING(POWER_CONSTRAINT);
1601 MFIE_STRING(POWER_CAPABILITY);
1602 MFIE_STRING(TPC_REQUEST);
1603 MFIE_STRING(TPC_REPORT);
1604 MFIE_STRING(SUPP_CHANNELS);
1605 MFIE_STRING(CSA);
1606 MFIE_STRING(MEASURE_REQUEST);
1607 MFIE_STRING(MEASURE_REPORT);
1608 MFIE_STRING(QUIET);
1609 MFIE_STRING(IBSS_DFS);
1610 // MFIE_STRING(ERP_INFO);
1611 MFIE_STRING(RSN);
1612 MFIE_STRING(RATES_EX);
1613 MFIE_STRING(GENERIC);
1614 MFIE_STRING(QOS_PARAMETER);
1615 default:
1616 return "UNKNOWN";
1617 }
1618}
1619#endif
1620
1621#ifdef ENABLE_DOT11D
1622static inline void ieee80211_extract_country_ie(
1623 struct ieee80211_device *ieee,
1624 struct ieee80211_info_element *info_element,
1625 struct ieee80211_network *network,
1626 u8 * addr2
1627)
1628{
1629 if(IS_DOT11D_ENABLE(ieee))
1630 {
1631 if(info_element->len!= 0)
1632 {
1633 memcpy(network->CountryIeBuf, info_element->data, info_element->len);
1634 network->CountryIeLen = info_element->len;
1635
1636 if(!IS_COUNTRY_IE_VALID(ieee))
1637 {
1638 Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
1639 }
1640 }
1641
1642 //
1643 // 070305, rcnjko: I update country IE watch dog here because
1644 // some AP (e.g. Cisco 1242) don't include country IE in their
1645 // probe response frame.
1646 //
1647 if(IS_EQUAL_CIE_SRC(ieee, addr2) )
1648 {
1649 UPDATE_CIE_WATCHDOG(ieee);
1650 }
1651 }
1652
1653}
1654#endif
1655
1656int ieee80211_parse_info_param(struct ieee80211_device *ieee,
1657 struct ieee80211_info_element *info_element,
1658 u16 length,
1659 struct ieee80211_network *network,
1660 struct ieee80211_rx_stats *stats)
1661{
1662 u8 i;
1663 short offset;
1664 u16 tmp_htcap_len=0;
1665 u16 tmp_htinfo_len=0;
1666 u16 ht_realtek_agg_len=0;
1667 u8 ht_realtek_agg_buf[MAX_IE_LEN];
1668#ifdef CONFIG_IEEE80211_DEBUG
1669 char rates_str[64];
1670 char *p;
1671#endif
1672
1673 while (length >= sizeof(*info_element)) {
1674 if (sizeof(*info_element) + info_element->len > length) {
1675 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
1676 "info_element->len + 2 > left : "
1677 "info_element->len+2=%zd left=%d, id=%d.\n",
1678 info_element->len +
1679 sizeof(*info_element),
1680 length, info_element->id);
1681 /* We stop processing but don't return an error here
1682 * because some misbehaviour APs break this rule. ie.
1683 * Orinoco AP1000. */
1684 break;
1685 }
1686
1687 switch (info_element->id) {
1688 case MFIE_TYPE_SSID:
1689 if (ieee80211_is_empty_essid(info_element->data,
1690 info_element->len)) {
1691 network->flags |= NETWORK_EMPTY_ESSID;
1692 break;
1693 }
1694
1695 network->ssid_len = min(info_element->len,
1696 (u8) IW_ESSID_MAX_SIZE);
1697 memcpy(network->ssid, info_element->data, network->ssid_len);
1698 if (network->ssid_len < IW_ESSID_MAX_SIZE)
1699 memset(network->ssid + network->ssid_len, 0,
1700 IW_ESSID_MAX_SIZE - network->ssid_len);
1701
1702 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1703 network->ssid, network->ssid_len);
1704 break;
1705
1706 case MFIE_TYPE_RATES:
1707#ifdef CONFIG_IEEE80211_DEBUG
1708 p = rates_str;
1709#endif
1710 network->rates_len = min(info_element->len,
1711 MAX_RATES_LENGTH);
1712 for (i = 0; i < network->rates_len; i++) {
1713 network->rates[i] = info_element->data[i];
1714#ifdef CONFIG_IEEE80211_DEBUG
1715 p += snprintf(p, sizeof(rates_str) -
1716 (p - rates_str), "%02X ",
1717 network->rates[i]);
1718#endif
1719 if (ieee80211_is_ofdm_rate
1720 (info_element->data[i])) {
1721 network->flags |= NETWORK_HAS_OFDM;
1722 if (info_element->data[i] &
1723 IEEE80211_BASIC_RATE_MASK)
1724 network->flags &=
1725 ~NETWORK_HAS_CCK;
1726 }
1727 }
1728
1729 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1730 rates_str, network->rates_len);
1731 break;
1732
1733 case MFIE_TYPE_RATES_EX:
1734#ifdef CONFIG_IEEE80211_DEBUG
1735 p = rates_str;
1736#endif
1737 network->rates_ex_len = min(info_element->len,
1738 MAX_RATES_EX_LENGTH);
1739 for (i = 0; i < network->rates_ex_len; i++) {
1740 network->rates_ex[i] = info_element->data[i];
1741#ifdef CONFIG_IEEE80211_DEBUG
1742 p += snprintf(p, sizeof(rates_str) -
1743 (p - rates_str), "%02X ",
1744 network->rates[i]);
1745#endif
1746 if (ieee80211_is_ofdm_rate
1747 (info_element->data[i])) {
1748 network->flags |= NETWORK_HAS_OFDM;
1749 if (info_element->data[i] &
1750 IEEE80211_BASIC_RATE_MASK)
1751 network->flags &=
1752 ~NETWORK_HAS_CCK;
1753 }
1754 }
1755
1756 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1757 rates_str, network->rates_ex_len);
1758 break;
1759
1760 case MFIE_TYPE_DS_SET:
1761 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1762 info_element->data[0]);
1763 network->channel = info_element->data[0];
1764 break;
1765
1766 case MFIE_TYPE_FH_SET:
1767 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1768 break;
1769
1770 case MFIE_TYPE_CF_SET:
1771 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1772 break;
1773
1774 case MFIE_TYPE_TIM:
1775 if(info_element->len < 4)
1776 break;
1777
1778 network->tim.tim_count = info_element->data[0];
1779 network->tim.tim_period = info_element->data[1];
1780
1781 network->dtim_period = info_element->data[1];
1782 if(ieee->state != IEEE80211_LINKED)
1783 break;
1784 //we use jiffies for legacy Power save
1785 network->last_dtim_sta_time[0] = jiffies;
1786 network->last_dtim_sta_time[1] = stats->mac_time[1];
1787
1788 network->dtim_data = IEEE80211_DTIM_VALID;
1789
1790 if(info_element->data[0] != 0)
1791 break;
1792
1793 if(info_element->data[2] & 1)
1794 network->dtim_data |= IEEE80211_DTIM_MBCAST;
1795
1796 offset = (info_element->data[2] >> 1)*2;
1797
1798 if(ieee->assoc_id < 8*offset ||
1799 ieee->assoc_id > 8*(offset + info_element->len -3))
1800
1801 break;
1802
1803 offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ;
1804
1805 if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
1806 network->dtim_data |= IEEE80211_DTIM_UCAST;
1807
1808 break;
1809
1810 case MFIE_TYPE_ERP:
1811 network->erp_value = info_element->data[0];
1812 network->flags |= NETWORK_HAS_ERP_VALUE;
1813 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1814 network->erp_value);
1815 break;
1816 case MFIE_TYPE_IBSS_SET:
1817 network->atim_window = info_element->data[0];
1818 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1819 network->atim_window);
1820 break;
1821
1822 case MFIE_TYPE_CHALLENGE:
1823 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1824 break;
1825
1826 case MFIE_TYPE_GENERIC:
1827 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1828 info_element->len);
1829 if (!ieee80211_parse_qos_info_param_IE(info_element,
1830 network))
1831 break;
1832
1833 if (info_element->len >= 4 &&
1834 info_element->data[0] == 0x00 &&
1835 info_element->data[1] == 0x50 &&
1836 info_element->data[2] == 0xf2 &&
1837 info_element->data[3] == 0x01) {
1838 network->wpa_ie_len = min(info_element->len + 2,
1839 MAX_WPA_IE_LEN);
1840 memcpy(network->wpa_ie, info_element,
1841 network->wpa_ie_len);
1842 break;
1843 }
1844
1845#ifdef THOMAS_TURBO
1846 if (info_element->len == 7 &&
1847 info_element->data[0] == 0x00 &&
1848 info_element->data[1] == 0xe0 &&
1849 info_element->data[2] == 0x4c &&
1850 info_element->data[3] == 0x01 &&
1851 info_element->data[4] == 0x02) {
1852 network->Turbo_Enable = 1;
1853 }
1854#endif
1855
1856 //for HTcap and HTinfo parameters
1857 if(tmp_htcap_len == 0){
1858 if(info_element->len >= 4 &&
1859 info_element->data[0] == 0x00 &&
1860 info_element->data[1] == 0x90 &&
1861 info_element->data[2] == 0x4c &&
1862 info_element->data[3] == 0x033){
1863
1864 tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
1865 if(tmp_htcap_len != 0){
1866 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1867 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
1868 sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
1869 memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
1870 }
1871 }
1872 if(tmp_htcap_len != 0)
1873 network->bssht.bdSupportHT = true;
1874 else
1875 network->bssht.bdSupportHT = false;
1876 }
1877
1878
1879 if(tmp_htinfo_len == 0){
1880 if(info_element->len >= 4 &&
1881 info_element->data[0] == 0x00 &&
1882 info_element->data[1] == 0x90 &&
1883 info_element->data[2] == 0x4c &&
1884 info_element->data[3] == 0x034){
1885
1886 tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
1887 if(tmp_htinfo_len != 0){
1888 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1889 if(tmp_htinfo_len){
1890 network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
1891 sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
1892 memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
1893 }
1894
1895 }
1896
1897 }
1898 }
1899
1900 if(ieee->aggregation){
1901 if(network->bssht.bdSupportHT){
1902 if(info_element->len >= 4 &&
1903 info_element->data[0] == 0x00 &&
1904 info_element->data[1] == 0xe0 &&
1905 info_element->data[2] == 0x4c &&
1906 info_element->data[3] == 0x02){
1907
1908 ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN);
1909 memcpy(ht_realtek_agg_buf,info_element->data,info_element->len);
1910
1911 }
1912 if(ht_realtek_agg_len >= 5){
1913 network->bssht.bdRT2RTAggregation = true;
1914
1915 if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
1916 network->bssht.bdRT2RTLongSlotTime = true;
1917 }
1918 }
1919
1920 }
1921
1922 if((info_element->len >= 3 &&
1923 info_element->data[0] == 0x00 &&
1924 info_element->data[1] == 0x05 &&
1925 info_element->data[2] == 0xb5) ||
1926 (info_element->len >= 3 &&
1927 info_element->data[0] == 0x00 &&
1928 info_element->data[1] == 0x0a &&
1929 info_element->data[2] == 0xf7) ||
1930 (info_element->len >= 3 &&
1931 info_element->data[0] == 0x00 &&
1932 info_element->data[1] == 0x10 &&
1933 info_element->data[2] == 0x18)){
1934
1935 network->broadcom_cap_exist = true;
1936
1937 }
1938
1939 if(info_element->len >= 3 &&
1940 info_element->data[0] == 0x00 &&
1941 info_element->data[1] == 0x0c &&
1942 info_element->data[2] == 0x43)
1943 {
1944 network->ralink_cap_exist = true;
1945 }
1946 else
1947 network->ralink_cap_exist = false;
1948 //added by amy for atheros AP
1949 if((info_element->len >= 3 &&
1950 info_element->data[0] == 0x00 &&
1951 info_element->data[1] == 0x03 &&
1952 info_element->data[2] == 0x7f) ||
1953 (info_element->len >= 3 &&
1954 info_element->data[0] == 0x00 &&
1955 info_element->data[1] == 0x13 &&
1956 info_element->data[2] == 0x74))
1957 {
1958 network->atheros_cap_exist = true;
1959 }
1960 else
1961 network->atheros_cap_exist = false;
1962
1963 if ((info_element->len >= 3 &&
1964 info_element->data[0] == 0x00 &&
1965 info_element->data[1] == 0x50 &&
1966 info_element->data[2] == 0x43) )
1967 {
1968 network->marvell_cap_exist = true;
1969 }
1970
1971
1972 if(info_element->len >= 3 &&
1973 info_element->data[0] == 0x00 &&
1974 info_element->data[1] == 0x40 &&
1975 info_element->data[2] == 0x96)
1976 {
1977 network->cisco_cap_exist = true;
1978 }
1979 else
1980 network->cisco_cap_exist = false;
1981 //added by amy for LEAP of cisco
1982 if(info_element->len > 4 &&
1983 info_element->data[0] == 0x00 &&
1984 info_element->data[1] == 0x40 &&
1985 info_element->data[2] == 0x96 &&
1986 info_element->data[3] == 0x01)
1987 {
1988 if(info_element->len == 6)
1989 {
1990 memcpy(network->CcxRmState, &info_element[4], 2);
1991 if(network->CcxRmState[0] != 0)
1992 {
1993 network->bCcxRmEnable = true;
1994 }
1995 else
1996 network->bCcxRmEnable = false;
1997 //
1998 // CCXv4 Table 59-1 MBSSID Masks.
1999 //
2000 network->MBssidMask = network->CcxRmState[1] & 0x07;
2001 if(network->MBssidMask != 0)
2002 {
2003 network->bMBssidValid = true;
2004 network->MBssidMask = 0xff << (network->MBssidMask);
2005 cpMacAddr(network->MBssid, network->bssid);
2006 network->MBssid[5] &= network->MBssidMask;
2007 }
2008 else
2009 {
2010 network->bMBssidValid = false;
2011 }
2012 }
2013 else
2014 {
2015 network->bCcxRmEnable = false;
2016 }
2017 }
2018 if(info_element->len > 4 &&
2019 info_element->data[0] == 0x00 &&
2020 info_element->data[1] == 0x40 &&
2021 info_element->data[2] == 0x96 &&
2022 info_element->data[3] == 0x03)
2023 {
2024 if(info_element->len == 5)
2025 {
2026 network->bWithCcxVerNum = true;
2027 network->BssCcxVerNumber = info_element->data[4];
2028 }
2029 else
2030 {
2031 network->bWithCcxVerNum = false;
2032 network->BssCcxVerNumber = 0;
2033 }
2034 }
2035 break;
2036
2037 case MFIE_TYPE_RSN:
2038 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
2039 info_element->len);
2040 network->rsn_ie_len = min(info_element->len + 2,
2041 MAX_WPA_IE_LEN);
2042 memcpy(network->rsn_ie, info_element,
2043 network->rsn_ie_len);
2044 break;
2045
2046 //HT related element.
2047 case MFIE_TYPE_HT_CAP:
2048 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
2049 info_element->len);
2050 tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
2051 if(tmp_htcap_len != 0){
2052 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
2053 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
2054 sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
2055 memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
2056
2057 //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
2058 // windows driver will update WMM parameters each beacon received once connected
2059 // Linux driver is a bit different.
2060 network->bssht.bdSupportHT = true;
2061 }
2062 else
2063 network->bssht.bdSupportHT = false;
2064 break;
2065
2066
2067 case MFIE_TYPE_HT_INFO:
2068 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
2069 info_element->len);
2070 tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
2071 if(tmp_htinfo_len){
2072 network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
2073 network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
2074 sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
2075 memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
2076 }
2077 break;
2078
2079 case MFIE_TYPE_AIRONET:
2080 IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
2081 info_element->len);
2082 if(info_element->len >IE_CISCO_FLAG_POSITION)
2083 {
2084 network->bWithAironetIE = true;
2085
2086 // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23):
2087 // "A Cisco access point advertises support for CKIP in beacon and probe response packets,
2088 // by adding an Aironet element and setting one or both of the CKIP negotiation bits."
2089 if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) ||
2090 (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) )
2091 {
2092 network->bCkipSupported = true;
2093 }
2094 else
2095 {
2096 network->bCkipSupported = false;
2097 }
2098 }
2099 else
2100 {
2101 network->bWithAironetIE = false;
2102 network->bCkipSupported = false;
2103 }
2104 break;
2105 case MFIE_TYPE_QOS_PARAMETER:
2106 printk(KERN_ERR
2107 "QoS Error need to parse QOS_PARAMETER IE\n");
2108 break;
2109
2110#ifdef ENABLE_DOT11D
2111 case MFIE_TYPE_COUNTRY:
2112 IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
2113 info_element->len);
2114 ieee80211_extract_country_ie(ieee, info_element, network, network->bssid);//addr2 is same as addr3 when from an AP
2115 break;
2116#endif
2117
2118 default:
2119 IEEE80211_DEBUG_MGMT
2120 ("Unsupported info element: %s (%d)\n",
2121 get_info_element_string(info_element->id),
2122 info_element->id);
2123 break;
2124 }
2125
2126 length -= sizeof(*info_element) + info_element->len;
2127 info_element =
2128 (struct ieee80211_info_element *)&info_element->
2129 data[info_element->len];
2130 }
2131
2132 if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
2133 !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation &&
2134 !network->marvell_cap_exist)
2135 {
2136 network->unknown_cap_exist = true;
2137 }
2138 else
2139 {
2140 network->unknown_cap_exist = false;
2141 }
2142 return 0;
2143}
2144
2145static inline u8 ieee80211_SignalStrengthTranslate(
2146 u8 CurrSS
2147 )
2148{
2149 u8 RetSS;
2150
2151 // Step 1. Scale mapping.
2152 if(CurrSS >= 71 && CurrSS <= 100)
2153 {
2154 RetSS = 90 + ((CurrSS - 70) / 3);
2155 }
2156 else if(CurrSS >= 41 && CurrSS <= 70)
2157 {
2158 RetSS = 78 + ((CurrSS - 40) / 3);
2159 }
2160 else if(CurrSS >= 31 && CurrSS <= 40)
2161 {
2162 RetSS = 66 + (CurrSS - 30);
2163 }
2164 else if(CurrSS >= 21 && CurrSS <= 30)
2165 {
2166 RetSS = 54 + (CurrSS - 20);
2167 }
2168 else if(CurrSS >= 5 && CurrSS <= 20)
2169 {
2170 RetSS = 42 + (((CurrSS - 5) * 2) / 3);
2171 }
2172 else if(CurrSS == 4)
2173 {
2174 RetSS = 36;
2175 }
2176 else if(CurrSS == 3)
2177 {
2178 RetSS = 27;
2179 }
2180 else if(CurrSS == 2)
2181 {
2182 RetSS = 18;
2183 }
2184 else if(CurrSS == 1)
2185 {
2186 RetSS = 9;
2187 }
2188 else
2189 {
2190 RetSS = CurrSS;
2191 }
2192
2193 return RetSS;
2194}
2195
2196long ieee80211_translate_todbm(u8 signal_strength_index )// 0-100 index.
2197{
2198 long signal_power; // in dBm.
2199
2200 // Translate to dBm (x=0.5y-95).
2201 signal_power = (long)((signal_strength_index + 1) >> 1);
2202 signal_power -= 95;
2203
2204 return signal_power;
2205}
2206
2207static inline int ieee80211_network_init(
2208 struct ieee80211_device *ieee,
2209 struct ieee80211_probe_response *beacon,
2210 struct ieee80211_network *network,
2211 struct ieee80211_rx_stats *stats)
2212{
2213 network->qos_data.active = 0;
2214 network->qos_data.supported = 0;
2215 network->qos_data.param_count = 0;
2216 network->qos_data.old_param_count = 0;
2217
2218 /* Pull out fixed field data */
2219 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
2220 network->capability = le16_to_cpu(beacon->capability);
2221 network->last_scanned = jiffies;
2222 network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
2223 network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
2224 network->beacon_interval = le32_to_cpu(beacon->beacon_interval);
2225 /* Where to pull this? beacon->listen_interval;*/
2226 network->listen_interval = 0x0A;
2227 network->rates_len = network->rates_ex_len = 0;
2228 network->last_associate = 0;
2229 network->ssid_len = 0;
2230 network->flags = 0;
2231 network->atim_window = 0;
2232 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
2233 0x3 : 0x0;
2234 network->berp_info_valid = false;
2235 network->broadcom_cap_exist = false;
2236 network->ralink_cap_exist = false;
2237 network->atheros_cap_exist = false;
2238 network->marvell_cap_exist = false;
2239 network->cisco_cap_exist = false;
2240 network->unknown_cap_exist = false;
2241#ifdef THOMAS_TURBO
2242 network->Turbo_Enable = 0;
2243#endif
2244#ifdef ENABLE_DOT11D
2245 network->CountryIeLen = 0;
2246 memset(network->CountryIeBuf, 0, MAX_IE_LEN);
2247#endif
2248//Initialize HT parameters
2249 HTInitializeBssDesc(&network->bssht);
2250 if (stats->freq == IEEE80211_52GHZ_BAND) {
2251 /* for A band (No DS info) */
2252 network->channel = stats->received_channel;
2253 } else
2254 network->flags |= NETWORK_HAS_CCK;
2255
2256 network->wpa_ie_len = 0;
2257 network->rsn_ie_len = 0;
2258
2259 if (ieee80211_parse_info_param
2260 (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats))
2261 return 1;
2262
2263 network->mode = 0;
2264 if (stats->freq == IEEE80211_52GHZ_BAND)
2265 network->mode = IEEE_A;
2266 else {
2267 if (network->flags & NETWORK_HAS_OFDM)
2268 network->mode |= IEEE_G;
2269 if (network->flags & NETWORK_HAS_CCK)
2270 network->mode |= IEEE_B;
2271 }
2272
2273 if (network->mode == 0) {
2274 IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
2275 "network.\n",
2276 escape_essid(network->ssid,
2277 network->ssid_len),
2278 network->bssid);
2279 return 1;
2280 }
2281
2282 if(network->bssht.bdSupportHT){
2283 if(network->mode == IEEE_A)
2284 network->mode = IEEE_N_5G;
2285 else if(network->mode & (IEEE_G | IEEE_B))
2286 network->mode = IEEE_N_24G;
2287 }
2288 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
2289 network->flags |= NETWORK_EMPTY_ESSID;
2290
2291 stats->signal = 30 + (stats->SignalStrength * 70) / 100;
2292 stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25;
2293
2294 memcpy(&network->stats, stats, sizeof(network->stats));
2295
2296 return 0;
2297}
2298
2299static inline int is_same_network(struct ieee80211_network *src,
2300 struct ieee80211_network *dst, struct ieee80211_device* ieee)
2301{
2302 /* A network is only a duplicate if the channel, BSSID, ESSID
2303 * and the capability field (in particular IBSS and BSS) all match.
2304 * We treat all <hidden> with the same BSSID and channel
2305 * as one network */
2306 return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2307 (src->channel == dst->channel) &&
2308 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
2309 (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2310 ((src->capability & WLAN_CAPABILITY_IBSS) ==
2311 (dst->capability & WLAN_CAPABILITY_IBSS)) &&
2312 ((src->capability & WLAN_CAPABILITY_BSS) ==
2313 (dst->capability & WLAN_CAPABILITY_BSS)));
2314}
2315
2316static inline void update_network(struct ieee80211_network *dst,
2317 struct ieee80211_network *src)
2318{
2319 int qos_active;
2320 u8 old_param;
2321
2322 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
2323 dst->capability = src->capability;
2324 memcpy(dst->rates, src->rates, src->rates_len);
2325 dst->rates_len = src->rates_len;
2326 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
2327 dst->rates_ex_len = src->rates_ex_len;
2328 if(src->ssid_len > 0)
2329 {
2330 memset(dst->ssid, 0, dst->ssid_len);
2331 dst->ssid_len = src->ssid_len;
2332 memcpy(dst->ssid, src->ssid, src->ssid_len);
2333 }
2334 dst->mode = src->mode;
2335 dst->flags = src->flags;
2336 dst->time_stamp[0] = src->time_stamp[0];
2337 dst->time_stamp[1] = src->time_stamp[1];
2338 if (src->flags & NETWORK_HAS_ERP_VALUE)
2339 {
2340 dst->erp_value = src->erp_value;
2341 dst->berp_info_valid = src->berp_info_valid = true;
2342 }
2343 dst->beacon_interval = src->beacon_interval;
2344 dst->listen_interval = src->listen_interval;
2345 dst->atim_window = src->atim_window;
2346 dst->dtim_period = src->dtim_period;
2347 dst->dtim_data = src->dtim_data;
2348 dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
2349 dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
2350 memcpy(&dst->tim, &src->tim, sizeof(struct ieee80211_tim_parameters));
2351
2352 dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
2353 dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
2354 dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen;
2355 memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen);
2356 dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen;
2357 memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen);
2358 dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
2359 dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
2360 dst->broadcom_cap_exist = src->broadcom_cap_exist;
2361 dst->ralink_cap_exist = src->ralink_cap_exist;
2362 dst->atheros_cap_exist = src->atheros_cap_exist;
2363 dst->marvell_cap_exist = src->marvell_cap_exist;
2364 dst->cisco_cap_exist = src->cisco_cap_exist;
2365 dst->unknown_cap_exist = src->unknown_cap_exist;
2366 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
2367 dst->wpa_ie_len = src->wpa_ie_len;
2368 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
2369 dst->rsn_ie_len = src->rsn_ie_len;
2370
2371 dst->last_scanned = jiffies;
2372 /* qos related parameters */
2373 qos_active = dst->qos_data.active;
2374 old_param = dst->qos_data.param_count;
2375 if(dst->flags & NETWORK_HAS_QOS_MASK){
2376 //not update QOS paramter in beacon, as most AP will set all these parameter to 0.//WB
2377 }
2378 else {
2379 dst->qos_data.supported = src->qos_data.supported;
2380 dst->qos_data.param_count = src->qos_data.param_count;
2381 }
2382
2383 if(dst->qos_data.supported == 1) {
2384 dst->QoS_Enable = 1;
2385 if(dst->ssid_len)
2386 IEEE80211_DEBUG_QOS
2387 ("QoS the network %s is QoS supported\n",
2388 dst->ssid);
2389 else
2390 IEEE80211_DEBUG_QOS
2391 ("QoS the network is QoS supported\n");
2392 }
2393 dst->qos_data.active = qos_active;
2394 dst->qos_data.old_param_count = old_param;
2395
2396 /* dst->last_associate is not overwritten */
2397 dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
2398 if(src->wmm_param[0].ac_aci_acm_aifsn|| \
2399 src->wmm_param[1].ac_aci_acm_aifsn|| \
2400 src->wmm_param[2].ac_aci_acm_aifsn|| \
2401 src->wmm_param[3].ac_aci_acm_aifsn) {
2402 memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
2403 }
2404#ifdef THOMAS_TURBO
2405 dst->Turbo_Enable = src->Turbo_Enable;
2406#endif
2407
2408#ifdef ENABLE_DOT11D
2409 dst->CountryIeLen = src->CountryIeLen;
2410 memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
2411#endif
2412
2413 //added by amy for LEAP
2414 dst->bWithAironetIE = src->bWithAironetIE;
2415 dst->bCkipSupported = src->bCkipSupported;
2416 memcpy(dst->CcxRmState,src->CcxRmState,2);
2417 dst->bCcxRmEnable = src->bCcxRmEnable;
2418 dst->MBssidMask = src->MBssidMask;
2419 dst->bMBssidValid = src->bMBssidValid;
2420 memcpy(dst->MBssid,src->MBssid,6);
2421 dst->bWithCcxVerNum = src->bWithCcxVerNum;
2422 dst->BssCcxVerNumber = src->BssCcxVerNumber;
2423
2424}
2425
2426static inline int is_beacon(__le16 fc)
2427{
2428 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
2429}
2430
2431static inline void ieee80211_process_probe_response(
2432 struct ieee80211_device *ieee,
2433 struct ieee80211_probe_response *beacon,
2434 struct ieee80211_rx_stats *stats)
2435{
2436 struct ieee80211_network network;
2437 struct ieee80211_network *target;
2438 struct ieee80211_network *oldest = NULL;
2439#ifdef CONFIG_IEEE80211_DEBUG
2440 struct ieee80211_info_element *info_element = &beacon->info_element[0];
2441#endif
2442 unsigned long flags;
2443 short renew;
2444
2445 memset(&network, 0, sizeof(struct ieee80211_network));
2446 IEEE80211_DEBUG_SCAN(
2447 "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
2448 escape_essid(info_element->data, info_element->len),
2449 beacon->header.addr3,
2450 (beacon->capability & (1<<0xf)) ? '1' : '0',
2451 (beacon->capability & (1<<0xe)) ? '1' : '0',
2452 (beacon->capability & (1<<0xd)) ? '1' : '0',
2453 (beacon->capability & (1<<0xc)) ? '1' : '0',
2454 (beacon->capability & (1<<0xb)) ? '1' : '0',
2455 (beacon->capability & (1<<0xa)) ? '1' : '0',
2456 (beacon->capability & (1<<0x9)) ? '1' : '0',
2457 (beacon->capability & (1<<0x8)) ? '1' : '0',
2458 (beacon->capability & (1<<0x7)) ? '1' : '0',
2459 (beacon->capability & (1<<0x6)) ? '1' : '0',
2460 (beacon->capability & (1<<0x5)) ? '1' : '0',
2461 (beacon->capability & (1<<0x4)) ? '1' : '0',
2462 (beacon->capability & (1<<0x3)) ? '1' : '0',
2463 (beacon->capability & (1<<0x2)) ? '1' : '0',
2464 (beacon->capability & (1<<0x1)) ? '1' : '0',
2465 (beacon->capability & (1<<0x0)) ? '1' : '0');
2466
2467 if (ieee80211_network_init(ieee, beacon, &network, stats)) {
2468 IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
2469 escape_essid(info_element->data,
2470 info_element->len),
2471 beacon->header.addr3,
2472 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2473 IEEE80211_STYPE_PROBE_RESP ?
2474 "PROBE RESPONSE" : "BEACON");
2475 return;
2476 }
2477
2478#ifdef ENABLE_DOT11D
2479 // For Asus EeePc request,
2480 // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
2481 // wireless adapter should follow the country code.
2482 // (2) If there is no any country code in beacon,
2483 // then wireless adapter should do active scan from ch1~11 and
2484 // passive scan from ch12~14
2485
2486 if( !IsLegalChannel(ieee, network.channel) )
2487 return;
2488 if(ieee->bGlobalDomain)
2489 {
2490 if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
2491 {
2492 // Case 1: Country code
2493 if(IS_COUNTRY_IE_VALID(ieee) )
2494 {
2495 if( !IsLegalChannel(ieee, network.channel) )
2496 {
2497 printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
2498 return;
2499 }
2500 }
2501 // Case 2: No any country code.
2502 else
2503 {
2504 // Filter over channel ch12~14
2505 if(network.channel > 11)
2506 {
2507 printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
2508 return;
2509 }
2510 }
2511 }
2512 else
2513 {
2514 // Case 1: Country code
2515 if(IS_COUNTRY_IE_VALID(ieee) )
2516 {
2517 if( !IsLegalChannel(ieee, network.channel) )
2518 {
2519 printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
2520 return;
2521 }
2522 }
2523 // Case 2: No any country code.
2524 else
2525 {
2526 // Filter over channel ch12~14
2527 if(network.channel > 14)
2528 {
2529 printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
2530 return;
2531 }
2532 }
2533 }
2534 }
2535#endif
2536
2537 /* The network parsed correctly -- so now we scan our known networks
2538 * to see if we can find it in our list.
2539 *
2540 * NOTE: This search is definitely not optimized. Once its doing
2541 * the "right thing" we'll optimize it for efficiency if
2542 * necessary */
2543
2544 /* Search for this entry in the list and update it if it is
2545 * already there. */
2546
2547 spin_lock_irqsave(&ieee->lock, flags);
2548
2549 if(is_same_network(&ieee->current_network, &network, ieee)) {
2550 update_network(&ieee->current_network, &network);
2551 if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
2552 && ieee->current_network.berp_info_valid){
2553 if(ieee->current_network.erp_value& ERP_UseProtection)
2554 ieee->current_network.buseprotection = true;
2555 else
2556 ieee->current_network.buseprotection = false;
2557 }
2558 if(is_beacon(beacon->header.frame_ctl))
2559 {
2560 if(ieee->state == IEEE80211_LINKED)
2561 ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
2562 }
2563 else //hidden AP
2564 network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
2565 }
2566
2567 list_for_each_entry(target, &ieee->network_list, list) {
2568 if (is_same_network(target, &network, ieee))
2569 break;
2570 if ((oldest == NULL) ||
2571 (target->last_scanned < oldest->last_scanned))
2572 oldest = target;
2573 }
2574
2575 /* If we didn't find a match, then get a new network slot to initialize
2576 * with this beacon's information */
2577 if (&target->list == &ieee->network_list) {
2578 if (list_empty(&ieee->network_free_list)) {
2579 /* If there are no more slots, expire the oldest */
2580 list_del(&oldest->list);
2581 target = oldest;
2582 IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
2583 "network list.\n",
2584 escape_essid(target->ssid,
2585 target->ssid_len),
2586 target->bssid);
2587 } else {
2588 /* Otherwise just pull from the free list */
2589 target = list_entry(ieee->network_free_list.next,
2590 struct ieee80211_network, list);
2591 list_del(ieee->network_free_list.next);
2592 }
2593
2594
2595#ifdef CONFIG_IEEE80211_DEBUG
2596 IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
2597 escape_essid(network.ssid,
2598 network.ssid_len),
2599 network.bssid,
2600 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2601 IEEE80211_STYPE_PROBE_RESP ?
2602 "PROBE RESPONSE" : "BEACON");
2603#endif
2604 memcpy(target, &network, sizeof(*target));
2605 list_add_tail(&target->list, &ieee->network_list);
2606 } else {
2607 IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
2608 escape_essid(target->ssid,
2609 target->ssid_len),
2610 target->bssid,
2611 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2612 IEEE80211_STYPE_PROBE_RESP ?
2613 "PROBE RESPONSE" : "BEACON");
2614
2615 /* we have an entry and we are going to update it. But this entry may
2616 * be already expired. In this case we do the same as we found a new
2617 * net and call the new_net handler
2618 */
2619 renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
2620 //YJ,add,080819,for hidden ap
2621 if(is_beacon(beacon->header.frame_ctl) == 0)
2622 network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
2623 if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
2624 && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
2625 ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
2626 renew = 1;
2627 //YJ,add,080819,for hidden ap,end
2628
2629 update_network(target, &network);
2630 }
2631
2632 spin_unlock_irqrestore(&ieee->lock, flags);
2633 if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
2634 (ieee->state == IEEE80211_LINKED)) {
2635 if(ieee->handle_beacon != NULL) {
2636 ieee->handle_beacon(ieee, beacon, &ieee->current_network);
2637 }
2638 }
2639}
2640
2641void ieee80211_rx_mgt(struct ieee80211_device *ieee,
2642 struct ieee80211_hdr_4addr *header,
2643 struct ieee80211_rx_stats *stats)
2644{
2645 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2646 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2647 ieee->last_rx_ps_time = jiffies;
2648
2649 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2650
2651 case IEEE80211_STYPE_BEACON:
2652 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
2653 WLAN_FC_GET_STYPE(header->frame_ctl));
2654 IEEE80211_DEBUG_SCAN("Beacon\n");
2655 ieee80211_process_probe_response(
2656 ieee, (struct ieee80211_probe_response *)header, stats);
2657
2658 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2659 ieee->iw_mode == IW_MODE_INFRA &&
2660 ieee->state == IEEE80211_LINKED))
2661 {
2662 tasklet_schedule(&ieee->ps_task);
2663 }
2664
2665 break;
2666
2667 case IEEE80211_STYPE_PROBE_RESP:
2668 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
2669 WLAN_FC_GET_STYPE(header->frame_ctl));
2670 IEEE80211_DEBUG_SCAN("Probe response\n");
2671 ieee80211_process_probe_response(
2672 ieee, (struct ieee80211_probe_response *)header, stats);
2673 break;
2674
2675 }
2676}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
new file mode 100644
index 00000000000..60e9a09d933
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -0,0 +1,3278 @@
1/* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
9 *
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18
19#include <linux/random.h>
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <asm/uaccess.h>
23#ifdef ENABLE_DOT11D
24#include "dot11d.h"
25#endif
26
27u8 rsn_authen_cipher_suite[16][4] = {
28 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
29 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
30 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
31 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
32 {0x00,0x0F,0xAC,0x04}, //CCMP
33 {0x00,0x0F,0xAC,0x05}, //WEP-104
34};
35
36short ieee80211_is_54g(struct ieee80211_network net)
37{
38 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39}
40
41short ieee80211_is_shortslot(struct ieee80211_network net)
42{
43 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
44}
45
46/* returns the total length needed for pleacing the RATE MFIE
47 * tag and the EXTENDED RATE MFIE tag if needed.
48 * It encludes two bytes per tag for the tag itself and its len
49 */
50unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
51{
52 unsigned int rate_len = 0;
53
54 if (ieee->modulation & IEEE80211_CCK_MODULATION)
55 rate_len = IEEE80211_CCK_RATE_LEN + 2;
56
57 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
58
59 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
60
61 return rate_len;
62}
63
64/* pleace the MFIE rate, tag to the memory (double) poined.
65 * Then it updates the pointer so that
66 * it points after the new MFIE tag added.
67 */
68void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
69{
70 u8 *tag = *tag_p;
71
72 if (ieee->modulation & IEEE80211_CCK_MODULATION){
73 *tag++ = MFIE_TYPE_RATES;
74 *tag++ = 4;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
78 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
79 }
80
81 /* We may add an option for custom rates that specific HW might support */
82 *tag_p = tag;
83}
84
85void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
86{
87 u8 *tag = *tag_p;
88
89 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
90
91 *tag++ = MFIE_TYPE_RATES_EX;
92 *tag++ = 8;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
100 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
101
102 }
103
104 /* We may add an option for custom rates that specific HW might support */
105 *tag_p = tag;
106}
107
108
109void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
110 u8 *tag = *tag_p;
111
112 *tag++ = MFIE_TYPE_GENERIC; //0
113 *tag++ = 7;
114 *tag++ = 0x00;
115 *tag++ = 0x50;
116 *tag++ = 0xf2;
117 *tag++ = 0x02;//5
118 *tag++ = 0x00;
119 *tag++ = 0x01;
120#ifdef SUPPORT_USPD
121 if(ieee->current_network.wmm_info & 0x80) {
122 *tag++ = 0x0f|MAX_SP_Len;
123 } else {
124 *tag++ = MAX_SP_Len;
125 }
126#else
127 *tag++ = MAX_SP_Len;
128#endif
129 *tag_p = tag;
130}
131
132#ifdef THOMAS_TURBO
133void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
134 u8 *tag = *tag_p;
135
136 *tag++ = MFIE_TYPE_GENERIC; //0
137 *tag++ = 7;
138 *tag++ = 0x00;
139 *tag++ = 0xe0;
140 *tag++ = 0x4c;
141 *tag++ = 0x01;//5
142 *tag++ = 0x02;
143 *tag++ = 0x11;
144 *tag++ = 0x00;
145
146 *tag_p = tag;
147 printk(KERN_ALERT "This is enable turbo mode IE process\n");
148}
149#endif
150
151void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
152{
153 int nh;
154 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
155
156/*
157 * if the queue is full but we have newer frames then
158 * just overwrites the oldest.
159 *
160 * if (nh == ieee->mgmt_queue_tail)
161 * return -1;
162 */
163 ieee->mgmt_queue_head = nh;
164 ieee->mgmt_queue_ring[nh] = skb;
165}
166
167struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
168{
169 struct sk_buff *ret;
170
171 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
172 return NULL;
173
174 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
175
176 ieee->mgmt_queue_tail =
177 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
178
179 return ret;
180}
181
182void init_mgmt_queue(struct ieee80211_device *ieee)
183{
184 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
185}
186
187u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
188{
189 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
190 u8 rate;
191
192 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
193 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
194 rate = 0x0c;
195 else
196 rate = ieee->basic_rate & 0x7f;
197
198 if(rate == 0){
199 // 2005.01.26, by rcnjko.
200 if(ieee->mode == IEEE_A||
201 ieee->mode== IEEE_N_5G||
202 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
203 rate = 0x0c;
204 else
205 rate = 0x02;
206 }
207
208 return rate;
209}
210
211
212void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
213
214inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
215{
216 unsigned long flags;
217 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
218 struct ieee80211_hdr_3addr *header=
219 (struct ieee80211_hdr_3addr *) skb->data;
220
221 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
222 spin_lock_irqsave(&ieee->lock, flags);
223
224 /* called with 2nd param 0, no mgmt lock required */
225 ieee80211_sta_wakeup(ieee,0);
226
227 tcb_desc->queue_index = MGNT_QUEUE;
228 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
229 tcb_desc->RATRIndex = 7;
230 tcb_desc->bTxDisableRateFallBack = 1;
231 tcb_desc->bTxUseDriverAssingedRate = 1;
232
233 if(single){
234 if(ieee->queue_stop){
235 enqueue_mgmt(ieee,skb);
236 }else{
237 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
238
239 if (ieee->seq_ctrl[0] == 0xFFF)
240 ieee->seq_ctrl[0] = 0;
241 else
242 ieee->seq_ctrl[0]++;
243
244 /* avoid watchdog triggers */
245 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
246 }
247
248 spin_unlock_irqrestore(&ieee->lock, flags);
249 }else{
250 spin_unlock_irqrestore(&ieee->lock, flags);
251 spin_lock(&ieee->mgmt_tx_lock);
252
253 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
254
255 if (ieee->seq_ctrl[0] == 0xFFF)
256 ieee->seq_ctrl[0] = 0;
257 else
258 ieee->seq_ctrl[0]++;
259
260 /* check wether the managed packet queued greater than 5 */
261 if(!ieee->check_nic_enough_desc(ieee, tcb_desc->queue_index)||
262 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||
263 (ieee->queue_stop) ) {
264 /* insert the skb packet to the management queue */
265 /* as for the completion function, it does not need
266 * to check it any more.
267 * */
268 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
269 } else {
270 ieee->softmac_hard_start_xmit(skb, ieee);
271 }
272 spin_unlock(&ieee->mgmt_tx_lock);
273 }
274}
275
276inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
277{
278
279 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
280 struct ieee80211_hdr_3addr *header =
281 (struct ieee80211_hdr_3addr *) skb->data;
282 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
283
284 tcb_desc->queue_index = MGNT_QUEUE;
285 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
286 tcb_desc->RATRIndex = 7;
287 tcb_desc->bTxDisableRateFallBack = 1;
288 tcb_desc->bTxUseDriverAssingedRate = 1;
289 if(single){
290
291 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
292
293 if (ieee->seq_ctrl[0] == 0xFFF)
294 ieee->seq_ctrl[0] = 0;
295 else
296 ieee->seq_ctrl[0]++;
297
298 /* avoid watchdog triggers */
299 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
300
301 }else{
302
303 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
304
305 if (ieee->seq_ctrl[0] == 0xFFF)
306 ieee->seq_ctrl[0] = 0;
307 else
308 ieee->seq_ctrl[0]++;
309
310 ieee->softmac_hard_start_xmit(skb, ieee);
311
312 }
313}
314
315inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
316{
317 unsigned int len,rate_len;
318 u8 *tag;
319 struct sk_buff *skb;
320 struct ieee80211_probe_request *req;
321
322 len = ieee->current_network.ssid_len;
323
324 rate_len = ieee80211_MFIE_rate_len(ieee);
325
326 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
327 2 + len + rate_len + ieee->tx_headroom);
328 if (!skb)
329 return NULL;
330
331 skb_reserve(skb, ieee->tx_headroom);
332
333 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
334 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
335 req->header.duration_id = 0; //FIXME: is this OK ?
336
337 memset(req->header.addr1, 0xff, ETH_ALEN);
338 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
339 memset(req->header.addr3, 0xff, ETH_ALEN);
340
341 tag = (u8 *) skb_put(skb,len+2+rate_len);
342
343 *tag++ = MFIE_TYPE_SSID;
344 *tag++ = len;
345 memcpy(tag, ieee->current_network.ssid, len);
346 tag += len;
347
348 ieee80211_MFIE_Brate(ieee,&tag);
349 ieee80211_MFIE_Grate(ieee,&tag);
350 return skb;
351}
352
353struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
354void ieee80211_send_beacon(struct ieee80211_device *ieee)
355{
356 struct sk_buff *skb;
357 if(!ieee->ieee_up)
358 return;
359
360 skb = ieee80211_get_beacon_(ieee);
361
362 if (skb){
363 softmac_mgmt_xmit(skb, ieee);
364 ieee->softmac_stats.tx_beacons++;
365 }
366
367 if(ieee->beacon_txing && ieee->ieee_up){
368 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
369 }
370}
371
372
373void ieee80211_send_beacon_cb(unsigned long _ieee)
374{
375 struct ieee80211_device *ieee =
376 (struct ieee80211_device *) _ieee;
377 unsigned long flags;
378
379 spin_lock_irqsave(&ieee->beacon_lock, flags);
380 ieee80211_send_beacon(ieee);
381 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
382}
383
384
385void ieee80211_send_probe(struct ieee80211_device *ieee)
386{
387 struct sk_buff *skb;
388
389 skb = ieee80211_probe_req(ieee);
390 if (skb){
391 softmac_mgmt_xmit(skb, ieee);
392 ieee->softmac_stats.tx_probe_rq++;
393 }
394}
395
396void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
397{
398 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
399 ieee80211_send_probe(ieee);
400 ieee80211_send_probe(ieee);
401 }
402}
403
404/* this performs syncro scan blocking the caller until all channels
405 * in the allowed channel map has been checked.
406 */
407void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
408{
409 short ch = 0;
410#ifdef ENABLE_DOT11D
411 u8 channel_map[MAX_CHANNEL_NUMBER+1];
412 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
413#endif
414 down(&ieee->scan_sem);
415
416 while(1)
417 {
418
419 do{
420 ch++;
421 if (ch > MAX_CHANNEL_NUMBER)
422 goto out; /* scan completed */
423#ifdef ENABLE_DOT11D
424 }while(!channel_map[ch]);
425#else
426 }while(!ieee->channel_map[ch]);
427#endif
428
429 /* this function can be called in two situations
430 * 1- We have switched to ad-hoc mode and we are
431 * performing a complete syncro scan before conclude
432 * there are no interesting cell and to create a
433 * new one. In this case the link state is
434 * IEEE80211_NOLINK until we found an interesting cell.
435 * If so the ieee8021_new_net, called by the RX path
436 * will set the state to IEEE80211_LINKED, so we stop
437 * scanning
438 * 2- We are linked and the root uses run iwlist scan.
439 * So we switch to IEEE80211_LINKED_SCANNING to remember
440 * that we are still logically linked (not interested in
441 * new network events, despite for updating the net list,
442 * but we are temporarly 'unlinked' as the driver shall
443 * not filter RX frames and the channel is changing.
444 * So the only situation in witch are interested is to check
445 * if the state become LINKED because of the #1 situation
446 */
447
448 if (ieee->state == IEEE80211_LINKED)
449 goto out;
450 ieee->set_chan(ieee, ch);
451#ifdef ENABLE_DOT11D
452 if(channel_map[ch] == 1)
453#endif
454 ieee80211_send_probe_requests(ieee);
455
456 /* this prevent excessive time wait when we
457 * need to wait for a syncro scan to end..
458 */
459 if(ieee->state < IEEE80211_LINKED)
460 ;
461 else
462 if (ieee->sync_scan_hurryup)
463 goto out;
464
465
466 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
467
468 }
469out:
470 if(ieee->state < IEEE80211_LINKED){
471 ieee->actscanning = false;
472 up(&ieee->scan_sem);
473 }
474 else{
475 ieee->sync_scan_hurryup = 0;
476#ifdef ENABLE_DOT11D
477 if(IS_DOT11D_ENABLE(ieee))
478 DOT11D_ScanComplete(ieee);
479#endif
480 up(&ieee->scan_sem);
481}
482}
483
484
485void ieee80211_softmac_scan_wq(struct work_struct *work)
486{
487 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
488 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
489 static short watchdog = 0;
490 u8 last_channel = ieee->current_network.channel;
491#ifdef ENABLE_DOT11D
492 u8 channel_map[MAX_CHANNEL_NUMBER+1];
493 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
494#endif
495 if(!ieee->ieee_up)
496 return;
497 down(&ieee->scan_sem);
498 do{
499 ieee->current_network.channel =
500 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
501 if (watchdog++ > MAX_CHANNEL_NUMBER) {
502 /* if current channel is not in channel map, set to default channel. */
503#ifdef ENABLE_DOT11D
504 if (!channel_map[ieee->current_network.channel]) {
505#else
506 if (!ieee->channel_map[ieee->current_network.channel]) {
507#endif
508 ieee->current_network.channel = 6;
509 goto out; /* no good chans */
510 }
511 }
512#ifdef ENABLE_DOT11D
513 }while(!channel_map[ieee->current_network.channel]);
514#else
515 }while(!ieee->channel_map[ieee->current_network.channel]);
516#endif
517 if (ieee->scanning == 0 )
518 goto out;
519 ieee->set_chan(ieee, ieee->current_network.channel);
520#ifdef ENABLE_DOT11D
521 if(channel_map[ieee->current_network.channel] == 1)
522#endif
523 ieee80211_send_probe_requests(ieee);
524
525
526 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
527
528 up(&ieee->scan_sem);
529 return;
530out:
531#ifdef ENABLE_DOT11D
532 if(IS_DOT11D_ENABLE(ieee))
533 DOT11D_ScanComplete(ieee);
534#endif
535 ieee->current_network.channel = last_channel;
536 ieee->actscanning = false;
537 watchdog = 0;
538 ieee->scanning = 0;
539 up(&ieee->scan_sem);
540}
541
542void ieee80211_beacons_start(struct ieee80211_device *ieee)
543{
544 unsigned long flags;
545 spin_lock_irqsave(&ieee->beacon_lock,flags);
546
547 ieee->beacon_txing = 1;
548 ieee80211_send_beacon(ieee);
549
550 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
551}
552
553void ieee80211_beacons_stop(struct ieee80211_device *ieee)
554{
555 unsigned long flags;
556
557 spin_lock_irqsave(&ieee->beacon_lock,flags);
558
559 ieee->beacon_txing = 0;
560 del_timer_sync(&ieee->beacon_timer);
561
562 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
563
564}
565
566
567void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
568{
569 if(ieee->stop_send_beacons)
570 ieee->stop_send_beacons(ieee);
571 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
572 ieee80211_beacons_stop(ieee);
573}
574
575
576void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
577{
578 if(ieee->start_send_beacons)
579 ieee->start_send_beacons(ieee);
580 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
581 ieee80211_beacons_start(ieee);
582}
583
584
585void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
586{
587 down(&ieee->scan_sem);
588
589 if (ieee->scanning == 1){
590 ieee->scanning = 0;
591
592 cancel_delayed_work(&ieee->softmac_scan_wq);
593 }
594
595 up(&ieee->scan_sem);
596}
597
598void ieee80211_stop_scan(struct ieee80211_device *ieee)
599{
600 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
601 ieee80211_softmac_stop_scan(ieee);
602 else
603 ieee->stop_scan(ieee);
604}
605
606/* called with ieee->lock held */
607void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
608{
609#ifdef ENABLE_IPS
610 if(ieee->ieee80211_ips_leave_wq != NULL)
611 ieee->ieee80211_ips_leave_wq(ieee);
612#endif
613
614#ifdef ENABLE_DOT11D
615 if(IS_DOT11D_ENABLE(ieee) )
616 {
617 if(IS_COUNTRY_IE_VALID(ieee))
618 {
619 RESET_CIE_WATCHDOG(ieee);
620 }
621 }
622#endif
623 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
624 if (ieee->scanning == 0){
625 ieee->scanning = 1;
626 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
627 }
628 }else
629 ieee->start_scan(ieee);
630
631}
632
633/* called with wx_sem held */
634void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
635{
636#ifdef ENABLE_DOT11D
637 if(IS_DOT11D_ENABLE(ieee) )
638 {
639 if(IS_COUNTRY_IE_VALID(ieee))
640 {
641 RESET_CIE_WATCHDOG(ieee);
642 }
643 }
644#endif
645 ieee->sync_scan_hurryup = 0;
646 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
647 ieee80211_softmac_scan_syncro(ieee);
648 else
649 ieee->scan_syncro(ieee);
650
651}
652
653inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
654 struct ieee80211_device *ieee, int challengelen)
655{
656 struct sk_buff *skb;
657 struct ieee80211_authentication *auth;
658 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
659
660
661 skb = dev_alloc_skb(len);
662 if (!skb) return NULL;
663
664 skb_reserve(skb, ieee->tx_headroom);
665 auth = (struct ieee80211_authentication *)
666 skb_put(skb, sizeof(struct ieee80211_authentication));
667
668 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
669 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
670
671 auth->header.duration_id = 0x013a; //FIXME
672
673 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
674 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
675 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
676
677 if(ieee->auth_mode == 0)
678 auth->algorithm = WLAN_AUTH_OPEN;
679 else if(ieee->auth_mode == 1)
680 auth->algorithm = WLAN_AUTH_SHARED_KEY;
681 else if(ieee->auth_mode == 2)
682 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
683 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
684 auth->transaction = cpu_to_le16(ieee->associate_seq);
685 ieee->associate_seq++;
686
687 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
688
689 return skb;
690
691}
692
693
694static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
695{
696 u8 *tag;
697 int beacon_size;
698 struct ieee80211_probe_response *beacon_buf;
699 struct sk_buff *skb = NULL;
700 int encrypt;
701 int atim_len,erp_len;
702 struct ieee80211_crypt_data* crypt;
703
704 char *ssid = ieee->current_network.ssid;
705 int ssid_len = ieee->current_network.ssid_len;
706 int rate_len = ieee->current_network.rates_len+2;
707 int rate_ex_len = ieee->current_network.rates_ex_len;
708 int wpa_ie_len = ieee->wpa_ie_len;
709 u8 erpinfo_content = 0;
710
711 u8* tmp_ht_cap_buf;
712 u8 tmp_ht_cap_len=0;
713 u8* tmp_ht_info_buf;
714 u8 tmp_ht_info_len=0;
715 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
716 u8* tmp_generic_ie_buf=NULL;
717 u8 tmp_generic_ie_len=0;
718
719 if(rate_ex_len > 0) rate_ex_len+=2;
720
721 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
722 atim_len = 4;
723 else
724 atim_len = 0;
725
726 if(ieee80211_is_54g(ieee->current_network))
727 erp_len = 3;
728 else
729 erp_len = 0;
730
731 crypt = ieee->crypt[ieee->tx_keyidx];
732
733
734 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
735 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
736 //HT ralated element
737
738 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
739 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
740 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
741 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
742 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
743 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
744
745
746 if(pHTInfo->bRegRT2RTAggregation)
747 {
748 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
749 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
750 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
751 }
752
753 beacon_size = sizeof(struct ieee80211_probe_response)+2+
754 ssid_len
755 +3 //channel
756 +rate_len
757 +rate_ex_len
758 +atim_len
759 +erp_len
760 +wpa_ie_len
761 +ieee->tx_headroom;
762 skb = dev_alloc_skb(beacon_size);
763 if (!skb)
764 return NULL;
765 skb_reserve(skb, ieee->tx_headroom);
766 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
767 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
768 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
769 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
770
771 beacon_buf->header.duration_id = 0; //FIXME
772 beacon_buf->beacon_interval =
773 cpu_to_le16(ieee->current_network.beacon_interval);
774 beacon_buf->capability =
775 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
776 beacon_buf->capability |=
777 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
778
779 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
780 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
781
782 crypt = ieee->crypt[ieee->tx_keyidx];
783 if (encrypt)
784 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
785
786
787 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
788 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
789 beacon_buf->info_element[0].len = ssid_len;
790
791 tag = (u8*) beacon_buf->info_element[0].data;
792
793 memcpy(tag, ssid, ssid_len);
794
795 tag += ssid_len;
796
797 *(tag++) = MFIE_TYPE_RATES;
798 *(tag++) = rate_len-2;
799 memcpy(tag,ieee->current_network.rates,rate_len-2);
800 tag+=rate_len-2;
801
802 *(tag++) = MFIE_TYPE_DS_SET;
803 *(tag++) = 1;
804 *(tag++) = ieee->current_network.channel;
805
806 if(atim_len){
807 u16 val16;
808 *(tag++) = MFIE_TYPE_IBSS_SET;
809 *(tag++) = 2;
810 val16 = cpu_to_le16(ieee->current_network.atim_window);
811 memcpy((u8 *)tag, (u8 *)&val16, 2);
812 tag+=2;
813 }
814
815 if(erp_len){
816 *(tag++) = MFIE_TYPE_ERP;
817 *(tag++) = 1;
818 *(tag++) = erpinfo_content;
819 }
820 if(rate_ex_len){
821 *(tag++) = MFIE_TYPE_RATES_EX;
822 *(tag++) = rate_ex_len-2;
823 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
824 tag+=rate_ex_len-2;
825 }
826
827 if (wpa_ie_len)
828 {
829 if (ieee->iw_mode == IW_MODE_ADHOC)
830 {//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07
831 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
832 }
833 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
834 tag += wpa_ie_len;
835 }
836
837 return skb;
838}
839
840
841struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
842{
843 struct sk_buff *skb;
844 u8* tag;
845
846 struct ieee80211_crypt_data* crypt;
847 struct ieee80211_assoc_response_frame *assoc;
848 short encrypt;
849
850 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
851 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
852
853 skb = dev_alloc_skb(len);
854
855 if (!skb)
856 return NULL;
857
858 skb_reserve(skb, ieee->tx_headroom);
859
860 assoc = (struct ieee80211_assoc_response_frame *)
861 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
862
863 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
864 memcpy(assoc->header.addr1, dest,ETH_ALEN);
865 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
866 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
867 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
868 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
869
870
871 if(ieee->short_slot)
872 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
873
874 if (ieee->host_encrypt)
875 crypt = ieee->crypt[ieee->tx_keyidx];
876 else crypt = NULL;
877
878 encrypt = ( crypt && crypt->ops);
879
880 if (encrypt)
881 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
882
883 assoc->status = 0;
884 assoc->aid = cpu_to_le16(ieee->assoc_id);
885 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
886 else ieee->assoc_id++;
887
888 tag = (u8*) skb_put(skb, rate_len);
889
890 ieee80211_MFIE_Brate(ieee, &tag);
891 ieee80211_MFIE_Grate(ieee, &tag);
892
893 return skb;
894}
895
896struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
897{
898 struct sk_buff *skb;
899 struct ieee80211_authentication *auth;
900 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
901
902 skb = dev_alloc_skb(len);
903
904 if (!skb)
905 return NULL;
906
907 skb->len = sizeof(struct ieee80211_authentication);
908
909 auth = (struct ieee80211_authentication *)skb->data;
910
911 auth->status = cpu_to_le16(status);
912 auth->transaction = cpu_to_le16(2);
913 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
914
915 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
916 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
917 memcpy(auth->header.addr1, dest, ETH_ALEN);
918 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
919 return skb;
920
921
922}
923
924struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
925{
926 struct sk_buff *skb;
927 struct ieee80211_hdr_3addr* hdr;
928
929 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
930
931 if (!skb)
932 return NULL;
933
934 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
935
936 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
937 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
938 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
939
940 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
941 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
942 (pwr ? IEEE80211_FCTL_PM:0));
943
944 return skb;
945
946
947}
948
949struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
950{
951 struct sk_buff *skb;
952 struct ieee80211_pspoll_hdr* hdr;
953
954#ifdef USB_USE_ALIGNMENT
955 u32 Tmpaddr=0;
956 int alignment=0;
957 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
958#else
959 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
960#endif
961 if (!skb)
962 return NULL;
963
964#ifdef USB_USE_ALIGNMENT
965 Tmpaddr = (u32)skb->data;
966 alignment = Tmpaddr & 0x1ff;
967 skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
968#endif
969 skb_reserve(skb, ieee->tx_headroom);
970
971 hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
972
973 memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
974 memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
975
976 hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
977 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
978
979 return skb;
980
981}
982
983
984void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
985{
986 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
987
988 if (buf)
989 softmac_mgmt_xmit(buf, ieee);
990}
991
992
993void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
994{
995 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
996
997 if (buf)
998 softmac_mgmt_xmit(buf, ieee);
999}
1000
1001
1002void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1003{
1004
1005
1006 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1007 if (buf)
1008 softmac_mgmt_xmit(buf, ieee);
1009}
1010
1011
1012inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1013{
1014 struct sk_buff *skb;
1015 struct ieee80211_assoc_request_frame *hdr;
1016 u8 *tag;
1017 u8* ht_cap_buf = NULL;
1018 u8 ht_cap_len=0;
1019 u8* realtek_ie_buf=NULL;
1020 u8 realtek_ie_len=0;
1021 int wpa_ie_len= ieee->wpa_ie_len;
1022 unsigned int ckip_ie_len=0;
1023 unsigned int ccxrm_ie_len=0;
1024 unsigned int cxvernum_ie_len=0;
1025 struct ieee80211_crypt_data* crypt;
1026 int encrypt;
1027
1028 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1029 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1030#ifdef THOMAS_TURBO
1031 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1032#endif
1033
1034 int len = 0;
1035
1036 crypt = ieee->crypt[ieee->tx_keyidx];
1037 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1038
1039 //Include High Throuput capability && Realtek proprietary
1040 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1041 {
1042 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1043 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1044 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1045 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1046 {
1047 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1048 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1049 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1050
1051 }
1052 }
1053 if(ieee->qos_support){
1054 wmm_info_len = beacon->qos_data.supported?9:0;
1055 }
1056
1057
1058 if(beacon->bCkipSupported)
1059 {
1060 ckip_ie_len = 30+2;
1061 }
1062 if(beacon->bCcxRmEnable)
1063 {
1064 ccxrm_ie_len = 6+2;
1065 }
1066 if( beacon->BssCcxVerNumber >= 2 )
1067 {
1068 cxvernum_ie_len = 5+2;
1069 }
1070#ifdef THOMAS_TURBO
1071 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1072 + beacon->ssid_len//essid tagged val
1073 + rate_len//rates tagged val
1074 + wpa_ie_len
1075 + wmm_info_len
1076 + turbo_info_len
1077 + ht_cap_len
1078 + realtek_ie_len
1079 + ckip_ie_len
1080 + ccxrm_ie_len
1081 + cxvernum_ie_len
1082 + ieee->tx_headroom;
1083#else
1084 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1085 + beacon->ssid_len//essid tagged val
1086 + rate_len//rates tagged val
1087 + wpa_ie_len
1088 + wmm_info_len
1089 + ht_cap_len
1090 + realtek_ie_len
1091 + ckip_ie_len
1092 + ccxrm_ie_len
1093 + cxvernum_ie_len
1094 + ieee->tx_headroom;
1095#endif
1096
1097 skb = dev_alloc_skb(len);
1098
1099 if (!skb)
1100 return NULL;
1101
1102 skb_reserve(skb, ieee->tx_headroom);
1103
1104 hdr = (struct ieee80211_assoc_request_frame *)
1105 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1106
1107
1108 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1109 hdr->header.duration_id= 37; //FIXME
1110 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1111 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1112 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1113
1114 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1115
1116 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1117 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1118 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1119
1120 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1121 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1122
1123 if(ieee->short_slot)
1124 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1125 if (wmm_info_len) //QOS
1126 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1127
1128 hdr->listen_interval = 0xa; //FIXME
1129
1130 hdr->info_element[0].id = MFIE_TYPE_SSID;
1131
1132 hdr->info_element[0].len = beacon->ssid_len;
1133 tag = skb_put(skb, beacon->ssid_len);
1134 memcpy(tag, beacon->ssid, beacon->ssid_len);
1135
1136 tag = skb_put(skb, rate_len);
1137
1138 ieee80211_MFIE_Brate(ieee, &tag);
1139 ieee80211_MFIE_Grate(ieee, &tag);
1140 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1141 if( beacon->bCkipSupported )
1142 {
1143 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1144 u8 CcxAironetBuf[30];
1145 OCTET_STRING osCcxAironetIE;
1146
1147 memset(CcxAironetBuf, 0,30);
1148 osCcxAironetIE.Octet = CcxAironetBuf;
1149 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1150 //
1151 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1152 // We want to make the device type as "4500-client". 060926, by CCW.
1153 //
1154 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1155
1156 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1157 // "The CKIP negotiation is started with the associate request from the client to the access point,
1158 // containing an Aironet element with both the MIC and KP bits set."
1159 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1160 tag = skb_put(skb, ckip_ie_len);
1161 *tag++ = MFIE_TYPE_AIRONET;
1162 *tag++ = osCcxAironetIE.Length;
1163 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1164 tag += osCcxAironetIE.Length;
1165 }
1166
1167 if(beacon->bCcxRmEnable)
1168 {
1169 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1170 OCTET_STRING osCcxRmCap;
1171
1172 osCcxRmCap.Octet = CcxRmCapBuf;
1173 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1174 tag = skb_put(skb,ccxrm_ie_len);
1175 *tag++ = MFIE_TYPE_GENERIC;
1176 *tag++ = osCcxRmCap.Length;
1177 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1178 tag += osCcxRmCap.Length;
1179 }
1180
1181 if( beacon->BssCcxVerNumber >= 2 )
1182 {
1183 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1184 OCTET_STRING osCcxVerNum;
1185 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1186 osCcxVerNum.Octet = CcxVerNumBuf;
1187 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1188 tag = skb_put(skb,cxvernum_ie_len);
1189 *tag++ = MFIE_TYPE_GENERIC;
1190 *tag++ = osCcxVerNum.Length;
1191 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1192 tag += osCcxVerNum.Length;
1193 }
1194 //HT cap element
1195 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1196 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1197 {
1198 tag = skb_put(skb, ht_cap_len);
1199 *tag++ = MFIE_TYPE_HT_CAP;
1200 *tag++ = ht_cap_len - 2;
1201 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1202 tag += ht_cap_len -2;
1203 }
1204 }
1205
1206
1207 //choose what wpa_supplicant gives to associate.
1208 tag = skb_put(skb, wpa_ie_len);
1209 if (wpa_ie_len){
1210 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1211 }
1212
1213 tag = skb_put(skb,wmm_info_len);
1214 if(wmm_info_len) {
1215 ieee80211_WMM_Info(ieee, &tag);
1216 }
1217#ifdef THOMAS_TURBO
1218 tag = skb_put(skb,turbo_info_len);
1219 if(turbo_info_len) {
1220 ieee80211_TURBO_Info(ieee, &tag);
1221 }
1222#endif
1223
1224 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1225 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1226 {
1227 tag = skb_put(skb, ht_cap_len);
1228 *tag++ = MFIE_TYPE_GENERIC;
1229 *tag++ = ht_cap_len - 2;
1230 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1231 tag += ht_cap_len -2;
1232 }
1233
1234 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1235 tag = skb_put(skb, realtek_ie_len);
1236 *tag++ = MFIE_TYPE_GENERIC;
1237 *tag++ = realtek_ie_len - 2;
1238 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1239 }
1240 }
1241 return skb;
1242}
1243
1244void ieee80211_associate_abort(struct ieee80211_device *ieee)
1245{
1246
1247 unsigned long flags;
1248 spin_lock_irqsave(&ieee->lock, flags);
1249
1250 ieee->associate_seq++;
1251
1252 /* don't scan, and avoid to have the RX path possibily
1253 * try again to associate. Even do not react to AUTH or
1254 * ASSOC response. Just wait for the retry wq to be scheduled.
1255 * Here we will check if there are good nets to associate
1256 * with, so we retry or just get back to NO_LINK and scanning
1257 */
1258 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1259 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1260 ieee->softmac_stats.no_auth_rs++;
1261 }else{
1262 IEEE80211_DEBUG_MGMT("Association failed\n");
1263 ieee->softmac_stats.no_ass_rs++;
1264 }
1265
1266 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1267
1268 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1269 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1270 spin_unlock_irqrestore(&ieee->lock, flags);
1271}
1272
1273void ieee80211_associate_abort_cb(unsigned long dev)
1274{
1275 ieee80211_associate_abort((struct ieee80211_device *) dev);
1276}
1277
1278
1279void ieee80211_associate_step1(struct ieee80211_device *ieee)
1280{
1281 struct ieee80211_network *beacon = &ieee->current_network;
1282 struct sk_buff *skb;
1283
1284 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1285
1286 ieee->softmac_stats.tx_auth_rq++;
1287 skb=ieee80211_authentication_req(beacon, ieee, 0);
1288
1289 if (!skb)
1290 ieee80211_associate_abort(ieee);
1291 else{
1292 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1293 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1294 softmac_mgmt_xmit(skb, ieee);
1295 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1296 if(!timer_pending(&ieee->associate_timer)){
1297 ieee->associate_timer.expires = jiffies + (HZ / 2);
1298 add_timer(&ieee->associate_timer);
1299 }
1300 }
1301}
1302
1303void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1304{
1305 u8 *c;
1306 struct sk_buff *skb;
1307 struct ieee80211_network *beacon = &ieee->current_network;
1308
1309 ieee->associate_seq++;
1310 ieee->softmac_stats.tx_auth_rq++;
1311
1312 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1313 if (!skb)
1314 ieee80211_associate_abort(ieee);
1315 else{
1316 c = skb_put(skb, chlen+2);
1317 *(c++) = MFIE_TYPE_CHALLENGE;
1318 *(c++) = chlen;
1319 memcpy(c, challenge, chlen);
1320
1321 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1322
1323 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1324
1325 softmac_mgmt_xmit(skb, ieee);
1326 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1327 }
1328 kfree(challenge);
1329}
1330
1331void ieee80211_associate_step2(struct ieee80211_device *ieee)
1332{
1333 struct sk_buff* skb;
1334 struct ieee80211_network *beacon = &ieee->current_network;
1335
1336 del_timer_sync(&ieee->associate_timer);
1337
1338 IEEE80211_DEBUG_MGMT("Sending association request\n");
1339
1340 ieee->softmac_stats.tx_ass_rq++;
1341 skb=ieee80211_association_req(beacon, ieee);
1342 if (!skb)
1343 ieee80211_associate_abort(ieee);
1344 else{
1345 softmac_mgmt_xmit(skb, ieee);
1346 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1347 }
1348}
1349void ieee80211_associate_complete_wq(struct work_struct *work)
1350{
1351 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1352 printk(KERN_INFO "Associated successfully\n");
1353 ieee->is_roaming = false;
1354 if(ieee80211_is_54g(ieee->current_network) &&
1355 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1356
1357 ieee->rate = 108;
1358 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1359 }else{
1360 ieee->rate = 22;
1361 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1362 }
1363 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1364 {
1365 printk("Successfully associated, ht enabled\n");
1366 HTOnAssocRsp(ieee);
1367 }
1368 else
1369 {
1370 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1371 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1372 }
1373 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1374 // To prevent the immediately calling watch_dog after association.
1375 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1376 {
1377 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1378 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1379 }
1380 ieee->link_change(ieee);
1381 if(ieee->is_silent_reset == 0){
1382 printk("============>normal associate\n");
1383 notify_wx_assoc_event(ieee);
1384 }
1385 else if(ieee->is_silent_reset == 1)
1386 {
1387 printk("==================>silent reset associate\n");
1388 ieee->is_silent_reset = 0;
1389 }
1390
1391 if (ieee->data_hard_resume)
1392 ieee->data_hard_resume(ieee);
1393 netif_carrier_on(ieee->dev);
1394}
1395
1396void ieee80211_associate_complete(struct ieee80211_device *ieee)
1397{
1398 del_timer_sync(&ieee->associate_timer);
1399
1400 ieee->state = IEEE80211_LINKED;
1401 queue_work(ieee->wq, &ieee->associate_complete_wq);
1402}
1403
1404void ieee80211_associate_procedure_wq(struct work_struct *work)
1405{
1406 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1407 ieee->sync_scan_hurryup = 1;
1408#ifdef ENABLE_IPS
1409 if(ieee->ieee80211_ips_leave != NULL)
1410 ieee->ieee80211_ips_leave(ieee);
1411#endif
1412
1413 down(&ieee->wx_sem);
1414
1415 if (ieee->data_hard_stop)
1416 ieee->data_hard_stop(ieee);
1417
1418 ieee80211_stop_scan(ieee);
1419 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1420 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1421
1422 ieee->associate_seq = 1;
1423 ieee80211_associate_step1(ieee);
1424
1425 up(&ieee->wx_sem);
1426}
1427
1428inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1429{
1430 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1431 int tmp_ssid_len = 0;
1432
1433 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1434
1435 /* we are interested in new new only if we are not associated
1436 * and we are not associating / authenticating
1437 */
1438 if (ieee->state != IEEE80211_NOLINK)
1439 return;
1440
1441 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1442 return;
1443
1444 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1445 return;
1446
1447
1448 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1449 /* if the user specified the AP MAC, we need also the essid
1450 * This could be obtained by beacons or, if the network does not
1451 * broadcast it, it can be put manually.
1452 */
1453 apset = ieee->wap_set;
1454 ssidset = ieee->ssid_set;
1455 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1456 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1457 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1458 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1459
1460
1461 if ( /* if the user set the AP check if match.
1462 * if the network does not broadcast essid we check the user supplyed ANY essid
1463 * if the network does broadcast and the user does not set essid it is OK
1464 * if the network does broadcast and the user did set essid chech if essid match
1465 */
1466 ( apset && apmatch &&
1467 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1468 /* if the ap is not set, check that the user set the bssid
1469 * and the network does bradcast and that those two bssid matches
1470 */
1471 (!apset && ssidset && ssidbroad && ssidmatch)
1472 ){
1473 /* if the essid is hidden replace it with the
1474 * essid provided by the user.
1475 */
1476 if (!ssidbroad){
1477 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1478 tmp_ssid_len = ieee->current_network.ssid_len;
1479 }
1480 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1481
1482 if (!ssidbroad){
1483 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1484 ieee->current_network.ssid_len = tmp_ssid_len;
1485 }
1486 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1487
1488 HTResetIOTSetting(ieee->pHTInfo);
1489 if (ieee->iw_mode == IW_MODE_INFRA){
1490 /* Join the network for the first time */
1491 ieee->AsocRetryCount = 0;
1492 //for HT by amy 080514
1493 if((ieee->current_network.qos_data.supported == 1) &&
1494 ieee->current_network.bssht.bdSupportHT)
1495/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
1496 {
1497 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1498 }
1499 else
1500 {
1501 ieee->pHTInfo->bCurrentHTSupport = false;
1502 }
1503
1504 ieee->state = IEEE80211_ASSOCIATING;
1505 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1506 }else{
1507 if(ieee80211_is_54g(ieee->current_network) &&
1508 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1509 ieee->rate = 108;
1510 ieee->SetWirelessMode(ieee, IEEE_G);
1511 printk(KERN_INFO"Using G rates\n");
1512 }else{
1513 ieee->rate = 22;
1514 ieee->SetWirelessMode(ieee, IEEE_B);
1515 printk(KERN_INFO"Using B rates\n");
1516 }
1517 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1518 ieee->state = IEEE80211_LINKED;
1519 }
1520
1521 }
1522 }
1523
1524}
1525
1526void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1527{
1528 unsigned long flags;
1529 struct ieee80211_network *target;
1530
1531 spin_lock_irqsave(&ieee->lock, flags);
1532
1533 list_for_each_entry(target, &ieee->network_list, list) {
1534
1535 /* if the state become different that NOLINK means
1536 * we had found what we are searching for
1537 */
1538
1539 if (ieee->state != IEEE80211_NOLINK)
1540 break;
1541
1542 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1543 ieee80211_softmac_new_net(ieee, target);
1544 }
1545
1546 spin_unlock_irqrestore(&ieee->lock, flags);
1547
1548}
1549
1550
1551static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1552{
1553 struct ieee80211_authentication *a;
1554 u8 *t;
1555 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1556 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1557 return 0xcafe;
1558 }
1559 *challenge = NULL;
1560 a = (struct ieee80211_authentication*) skb->data;
1561 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1562 t = skb->data + sizeof(struct ieee80211_authentication);
1563
1564 if(*(t++) == MFIE_TYPE_CHALLENGE){
1565 *chlen = *(t++);
1566 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1567 if (!*challenge)
1568 return -ENOMEM;
1569 }
1570 }
1571
1572 return cpu_to_le16(a->status);
1573
1574}
1575
1576
1577int auth_rq_parse(struct sk_buff *skb,u8* dest)
1578{
1579 struct ieee80211_authentication *a;
1580
1581 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1582 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1583 return -1;
1584 }
1585 a = (struct ieee80211_authentication*) skb->data;
1586
1587 memcpy(dest,a->header.addr2, ETH_ALEN);
1588
1589 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1590 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1591
1592 return WLAN_STATUS_SUCCESS;
1593}
1594
1595static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1596{
1597 u8 *tag;
1598 u8 *skbend;
1599 u8 *ssid=NULL;
1600 u8 ssidlen = 0;
1601
1602 struct ieee80211_hdr_3addr *header =
1603 (struct ieee80211_hdr_3addr *) skb->data;
1604
1605 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1606 return -1; /* corrupted */
1607
1608 memcpy(src,header->addr2, ETH_ALEN);
1609
1610 skbend = (u8*)skb->data + skb->len;
1611
1612 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1613
1614 while (tag+1 < skbend){
1615 if (*tag == 0){
1616 ssid = tag+2;
1617 ssidlen = *(tag+1);
1618 break;
1619 }
1620 tag++; /* point to the len field */
1621 tag = tag + *(tag); /* point to the last data byte of the tag */
1622 tag++; /* point to the next tag */
1623 }
1624
1625 if (ssidlen == 0) return 1;
1626
1627 if (!ssid) return 1; /* ssid not found in tagged param */
1628 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1629
1630}
1631
1632int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1633{
1634 struct ieee80211_assoc_request_frame *a;
1635
1636 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1637 sizeof(struct ieee80211_info_element))) {
1638
1639 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1640 return -1;
1641 }
1642
1643 a = (struct ieee80211_assoc_request_frame*) skb->data;
1644
1645 memcpy(dest,a->header.addr2,ETH_ALEN);
1646
1647 return 0;
1648}
1649
1650static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1651{
1652 struct ieee80211_assoc_response_frame *response_head;
1653 u16 status_code;
1654
1655 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1656 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1657 return 0xcafe;
1658 }
1659
1660 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1661 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1662
1663 status_code = le16_to_cpu(response_head->status);
1664 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1665 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1666 ((ieee->mode == IEEE_G) &&
1667 (ieee->current_network.mode == IEEE_N_24G) &&
1668 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1669 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1670 }else {
1671 ieee->AsocRetryCount = 0;
1672 }
1673
1674 return le16_to_cpu(response_head->status);
1675}
1676
1677static inline void
1678ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1679{
1680 u8 dest[ETH_ALEN];
1681
1682 ieee->softmac_stats.rx_probe_rq++;
1683 if (probe_rq_parse(ieee, skb, dest)){
1684 ieee->softmac_stats.tx_probe_rs++;
1685 ieee80211_resp_to_probe(ieee, dest);
1686 }
1687}
1688
1689static inline void
1690ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1691{
1692 u8 dest[ETH_ALEN];
1693 int status;
1694 ieee->softmac_stats.rx_auth_rq++;
1695
1696 status = auth_rq_parse(skb, dest);
1697 if (status != -1) {
1698 ieee80211_resp_to_auth(ieee, status, dest);
1699 }
1700}
1701
1702static inline void
1703ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1704{
1705 u8 dest[ETH_ALEN];
1706
1707 ieee->softmac_stats.rx_ass_rq++;
1708 if (assoc_rq_parse(skb,dest) != -1){
1709 ieee80211_resp_to_assoc_rq(ieee, dest);
1710 }
1711
1712 printk(KERN_INFO"New client associated: %pM\n", dest);
1713}
1714
1715
1716
1717void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1718{
1719
1720 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1721
1722 if (buf)
1723 softmac_ps_mgmt_xmit(buf, ieee);
1724
1725}
1726
1727void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1728{
1729
1730 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1731
1732 if (buf)
1733 softmac_ps_mgmt_xmit(buf, ieee);
1734
1735}
1736
1737short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1738{
1739 int timeout = ieee->ps_timeout;
1740 u8 dtim;
1741
1742 if(ieee->LPSDelayCnt)
1743 {
1744 ieee->LPSDelayCnt --;
1745 return 0;
1746 }
1747
1748 dtim = ieee->current_network.dtim_data;
1749 if(!(dtim & IEEE80211_DTIM_VALID))
1750 return 0;
1751 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1752 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1753 /* there's no need to nofity AP that I find you buffered with broadcast packet */
1754 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
1755 return 2;
1756
1757 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
1758 return 0;
1759 }
1760 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
1761 return 0;
1762 }
1763 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1764 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1765 return 0;
1766
1767 if(time_l){
1768 if(ieee->bAwakePktSent == true) {
1769 ieee->LPSAwakeIntvl = 1;//tx wake one beacon
1770 } else {
1771 u8 MaxPeriod = 1;
1772
1773 if(ieee->LPSAwakeIntvl == 0)
1774 ieee->LPSAwakeIntvl = 1;
1775 if(ieee->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
1776 MaxPeriod = 1; // 1 Beacon interval
1777 else if(ieee->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
1778 MaxPeriod = ieee->current_network.dtim_period;
1779 else
1780 MaxPeriod = ieee->RegMaxLPSAwakeIntvl;
1781 ieee->LPSAwakeIntvl = (ieee->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (ieee->LPSAwakeIntvl + 1);
1782 }
1783 {
1784 u8 LPSAwakeIntvl_tmp = 0;
1785 u8 period = ieee->current_network.dtim_period;
1786 u8 count = ieee->current_network.tim.tim_count;
1787 if(count == 0 ) {
1788 if(ieee->LPSAwakeIntvl > period)
1789 LPSAwakeIntvl_tmp = period + (ieee->LPSAwakeIntvl - period) -((ieee->LPSAwakeIntvl-period)%period);
1790 else
1791 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
1792
1793 } else {
1794 if(ieee->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
1795 LPSAwakeIntvl_tmp = count + (ieee->LPSAwakeIntvl - count) -((ieee->LPSAwakeIntvl-count)%period);
1796 else
1797 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
1798 }
1799
1800 *time_l = ieee->current_network.last_dtim_sta_time[0]
1801 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
1802 }
1803 }
1804
1805 if(time_h){
1806 *time_h = ieee->current_network.last_dtim_sta_time[1];
1807 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1808 *time_h += 1;
1809 }
1810
1811 return 1;
1812
1813
1814}
1815
1816inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1817{
1818
1819 u32 th,tl;
1820 short sleep;
1821 unsigned long flags;
1822
1823 spin_lock_irqsave(&ieee->lock, flags);
1824
1825 if((ieee->ps == IEEE80211_PS_DISABLED ||
1826 ieee->iw_mode != IW_MODE_INFRA ||
1827 ieee->state != IEEE80211_LINKED)){
1828
1829 // #warning CHECK_LOCK_HERE
1830 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
1831 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
1832 spin_lock(&ieee->mgmt_tx_lock);
1833
1834 ieee80211_sta_wakeup(ieee, 1);
1835
1836 spin_unlock(&ieee->mgmt_tx_lock);
1837 }
1838
1839 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1840 /* 2 wake, 1 sleep, 0 do nothing */
1841 if(sleep == 0)//it is not time out or dtim is not valid
1842 {
1843 goto out;
1844 }
1845 if(sleep == 1){
1846 if(ieee->sta_sleep == 1){
1847 ieee->enter_sleep_state(ieee, th, tl);
1848 }
1849
1850 else if(ieee->sta_sleep == 0){
1851 spin_lock(&ieee->mgmt_tx_lock);
1852
1853 if (ieee->ps_is_queue_empty(ieee)) {
1854 ieee->sta_sleep = 2;
1855 ieee->ack_tx_to_ieee = 1;
1856 ieee80211_sta_ps_send_null_frame(ieee,1);
1857 ieee->ps_th = th;
1858 ieee->ps_tl = tl;
1859 }
1860 spin_unlock(&ieee->mgmt_tx_lock);
1861
1862 }
1863
1864 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
1865
1866 }else if(sleep == 2){
1867 spin_lock(&ieee->mgmt_tx_lock);
1868
1869 ieee80211_sta_wakeup(ieee,1);
1870
1871 spin_unlock(&ieee->mgmt_tx_lock);
1872 }
1873
1874out:
1875 spin_unlock_irqrestore(&ieee->lock, flags);
1876
1877}
1878
1879void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1880{
1881 if(ieee->sta_sleep == 0){
1882 if(nl){
1883 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1884 {
1885 ieee->ack_tx_to_ieee = 1;
1886 ieee80211_sta_ps_send_null_frame(ieee, 0);
1887 }
1888 else
1889 {
1890 ieee->ack_tx_to_ieee = 1;
1891 ieee80211_sta_ps_send_pspoll_frame(ieee);
1892 }
1893 }
1894 return;
1895
1896 }
1897
1898 if(ieee->sta_sleep == 1)
1899 ieee->sta_wake_up(ieee);
1900 if(nl){
1901
1902 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1903 {
1904 ieee->ack_tx_to_ieee = 1;
1905 ieee80211_sta_ps_send_null_frame(ieee, 0);
1906 }
1907 else
1908 {
1909 ieee->ack_tx_to_ieee = 1;
1910 ieee->polling = true;
1911 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1912 ieee80211_sta_ps_send_pspoll_frame(ieee);
1913 }
1914
1915 } else {
1916 ieee->sta_sleep = 0;
1917 ieee->polling = false;
1918 }
1919}
1920
1921void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1922{
1923 unsigned long flags;
1924
1925 spin_lock_irqsave(&ieee->lock, flags);
1926
1927 if(ieee->sta_sleep == 2){
1928 /* Null frame with PS bit set */
1929 if(success){
1930 ieee->sta_sleep = 1;
1931 ieee->enter_sleep_state(ieee, ieee->ps_th, ieee->ps_tl);
1932 }
1933 } else {/* 21112005 - tx again null without PS bit if lost */
1934
1935 if((ieee->sta_sleep == 0) && !success){
1936 spin_lock(&ieee->mgmt_tx_lock);
1937 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1938 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1939 {
1940 ieee80211_sta_ps_send_null_frame(ieee, 0);
1941 }
1942 else
1943 {
1944 ieee80211_sta_ps_send_pspoll_frame(ieee);
1945 }
1946 spin_unlock(&ieee->mgmt_tx_lock);
1947 }
1948 }
1949 spin_unlock_irqrestore(&ieee->lock, flags);
1950}
1951
1952void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1953{
1954 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
1955 u8* act = ieee80211_get_payload(header);
1956 u8 tmp = 0;
1957
1958 if (act == NULL)
1959 {
1960 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1961 return;
1962 }
1963 tmp = *act;
1964 act ++;
1965 switch (tmp)
1966 {
1967 case ACT_CAT_BA:
1968 if (*act == ACT_ADDBAREQ)
1969 ieee80211_rx_ADDBAReq(ieee, skb);
1970 else if (*act == ACT_ADDBARSP)
1971 ieee80211_rx_ADDBARsp(ieee, skb);
1972 else if (*act == ACT_DELBA)
1973 ieee80211_rx_DELBA(ieee, skb);
1974 break;
1975 default:
1976 break;
1977 }
1978 return;
1979
1980}
1981inline int
1982ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1983 struct ieee80211_rx_stats *rx_stats, u16 type,
1984 u16 stype)
1985{
1986 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1987 u16 errcode;
1988 u8* challenge;
1989 int chlen=0;
1990 int aid;
1991 struct ieee80211_assoc_response_frame *assoc_resp;
1992 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1993
1994 if(!ieee->proto_started)
1995 return 0;
1996
1997 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1998
1999 case IEEE80211_STYPE_ASSOC_RESP:
2000 case IEEE80211_STYPE_REASSOC_RESP:
2001
2002 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2003 WLAN_FC_GET_STYPE(header->frame_ctl));
2004 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2005 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2006 ieee->iw_mode == IW_MODE_INFRA){
2007 struct ieee80211_network network_resp;
2008 struct ieee80211_network *network = &network_resp;
2009
2010 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2011 ieee->state=IEEE80211_LINKED;
2012 ieee->assoc_id = aid;
2013 ieee->softmac_stats.rx_ass_ok++;
2014 /* station support qos */
2015 /* Let the register setting defaultly with Legacy station */
2016 if(ieee->qos_support) {
2017 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2018 memset(network, 0, sizeof(*network));
2019 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2020 rx_stats->len - sizeof(*assoc_resp),\
2021 network,rx_stats)){
2022 return 1;
2023 }
2024 else
2025 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2026 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2027 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2028 }
2029 if (ieee->handle_assoc_response != NULL)
2030 ieee->handle_assoc_response(ieee, (struct ieee80211_assoc_response_frame*)header, network);
2031 }
2032 ieee80211_associate_complete(ieee);
2033 } else {
2034 /* aid could not been allocated */
2035 ieee->softmac_stats.rx_ass_err++;
2036 printk(
2037 "Association response status code 0x%x\n",
2038 errcode);
2039 IEEE80211_DEBUG_MGMT(
2040 "Association response status code 0x%x\n",
2041 errcode);
2042 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2043 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2044 } else {
2045 ieee80211_associate_abort(ieee);
2046 }
2047 }
2048 }
2049 break;
2050
2051 case IEEE80211_STYPE_ASSOC_REQ:
2052 case IEEE80211_STYPE_REASSOC_REQ:
2053
2054 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2055 ieee->iw_mode == IW_MODE_MASTER)
2056
2057 ieee80211_rx_assoc_rq(ieee, skb);
2058 break;
2059
2060 case IEEE80211_STYPE_AUTH:
2061
2062 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2063 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2064 ieee->iw_mode == IW_MODE_INFRA){
2065
2066 IEEE80211_DEBUG_MGMT("Received authentication response");
2067
2068 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2069 if(ieee->open_wep || !challenge){
2070 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2071 ieee->softmac_stats.rx_auth_rs_ok++;
2072 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2073 {
2074 if (!ieee->GetNmodeSupportBySecCfg(ieee))
2075 {
2076 // WEP or TKIP encryption
2077 if(IsHTHalfNmodeAPs(ieee))
2078 {
2079 bSupportNmode = true;
2080 bHalfSupportNmode = true;
2081 }
2082 else
2083 {
2084 bSupportNmode = false;
2085 bHalfSupportNmode = false;
2086 }
2087 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2088 }
2089 }
2090 /* Dummy wirless mode setting to avoid encryption issue */
2091 if(bSupportNmode) {
2092 //N mode setting
2093 ieee->SetWirelessMode(ieee,
2094 ieee->current_network.mode);
2095 }else{
2096 //b/g mode setting
2097 /*TODO*/
2098 ieee->SetWirelessMode(ieee, IEEE_G);
2099 }
2100
2101 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2102 {
2103 printk("===============>entern half N mode\n");
2104 ieee->bHalfWirelessN24GMode = true;
2105 }
2106 else
2107 ieee->bHalfWirelessN24GMode = false;
2108
2109 ieee80211_associate_step2(ieee);
2110 }else{
2111 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2112 }
2113 }else{
2114 ieee->softmac_stats.rx_auth_rs_err++;
2115 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2116
2117 printk("Authentication respose status code 0x%x",errcode);
2118 ieee80211_associate_abort(ieee);
2119 }
2120
2121 }else if (ieee->iw_mode == IW_MODE_MASTER){
2122 ieee80211_rx_auth_rq(ieee, skb);
2123 }
2124 }
2125 break;
2126
2127 case IEEE80211_STYPE_PROBE_REQ:
2128
2129 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2130 ((ieee->iw_mode == IW_MODE_ADHOC ||
2131 ieee->iw_mode == IW_MODE_MASTER) &&
2132 ieee->state == IEEE80211_LINKED)){
2133 ieee80211_rx_probe_rq(ieee, skb);
2134 }
2135 break;
2136
2137 case IEEE80211_STYPE_DISASSOC:
2138 case IEEE80211_STYPE_DEAUTH:
2139 /* FIXME for now repeat all the association procedure
2140 * both for disassociation and deauthentication
2141 */
2142 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2143 ieee->state == IEEE80211_LINKED &&
2144 ieee->iw_mode == IW_MODE_INFRA){
2145
2146 ieee->state = IEEE80211_ASSOCIATING;
2147 ieee->softmac_stats.reassoc++;
2148 ieee->is_roaming = true;
2149 ieee80211_disassociate(ieee);
2150 RemovePeerTS(ieee, header->addr2);
2151 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2152 }
2153 break;
2154 case IEEE80211_STYPE_MANAGE_ACT:
2155 ieee80211_process_action(ieee,skb);
2156 break;
2157 default:
2158 return -1;
2159 break;
2160 }
2161
2162 return 0;
2163}
2164
2165/* following are for a simpler TX queue management.
2166 * Instead of using netif_[stop/wake]_queue the driver
2167 * will uses these two function (plus a reset one), that
2168 * will internally uses the kernel netif_* and takes
2169 * care of the ieee802.11 fragmentation.
2170 * So the driver receives a fragment per time and might
2171 * call the stop function when it want without take care
2172 * to have enough room to TX an entire packet.
2173 * This might be useful if each fragment need it's own
2174 * descriptor, thus just keep a total free memory > than
2175 * the max fragmentation threshold is not enough.. If the
2176 * ieee802.11 stack passed a TXB struct then you needed
2177 * to keep N free descriptors where
2178 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2179 * In this way you need just one and the 802.11 stack
2180 * will take care of buffering fragments and pass them to
2181 * to the driver later, when it wakes the queue.
2182 */
2183void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2184{
2185
2186 unsigned int queue_index = txb->queue_index;
2187 unsigned long flags;
2188 int i;
2189 cb_desc *tcb_desc = NULL;
2190
2191 spin_lock_irqsave(&ieee->lock,flags);
2192
2193 /* called with 2nd parm 0, no tx mgmt lock required */
2194 ieee80211_sta_wakeup(ieee,0);
2195
2196 /* update the tx status */
2197 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2198 if(tcb_desc->bMulticast) {
2199 ieee->stats.multicast++;
2200 }
2201
2202 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2203 for(i = 0; i < txb->nr_frags; i++) {
2204#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2205 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2206#else
2207 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2208#endif
2209 (!ieee->check_nic_enough_desc(ieee, queue_index))||
2210 (ieee->queue_stop)) {
2211 /* insert the skb packet to the wait queue */
2212 /* as for the completion function, it does not need
2213 * to check it any more.
2214 * */
2215#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2216 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2217#else
2218 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2219#endif
2220 }else{
2221 ieee->softmac_data_hard_start_xmit(
2222 txb->fragments[i],
2223 ieee, ieee->rate);
2224 }
2225 }
2226
2227 ieee80211_txb_free(txb);
2228
2229 spin_unlock_irqrestore(&ieee->lock,flags);
2230
2231}
2232
2233/* called with ieee->lock acquired */
2234void ieee80211_resume_tx(struct ieee80211_device *ieee)
2235{
2236 int i;
2237 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2238
2239 if (ieee->queue_stop){
2240 ieee->tx_pending.frag = i;
2241 return;
2242 }else{
2243
2244 ieee->softmac_data_hard_start_xmit(
2245 ieee->tx_pending.txb->fragments[i],
2246 ieee, ieee->rate);
2247 ieee->stats.tx_packets++;
2248 }
2249 }
2250
2251
2252 ieee80211_txb_free(ieee->tx_pending.txb);
2253 ieee->tx_pending.txb = NULL;
2254}
2255
2256
2257void ieee80211_reset_queue(struct ieee80211_device *ieee)
2258{
2259 unsigned long flags;
2260
2261 spin_lock_irqsave(&ieee->lock,flags);
2262 init_mgmt_queue(ieee);
2263 if (ieee->tx_pending.txb){
2264 ieee80211_txb_free(ieee->tx_pending.txb);
2265 ieee->tx_pending.txb = NULL;
2266 }
2267 ieee->queue_stop = 0;
2268 spin_unlock_irqrestore(&ieee->lock,flags);
2269
2270}
2271
2272void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2273{
2274
2275 unsigned long flags;
2276 struct sk_buff *skb;
2277 struct ieee80211_hdr_3addr *header;
2278
2279 spin_lock_irqsave(&ieee->lock,flags);
2280 if (! ieee->queue_stop) goto exit;
2281
2282 ieee->queue_stop = 0;
2283
2284 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2285 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2286
2287 header = (struct ieee80211_hdr_3addr *) skb->data;
2288
2289 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2290
2291 if (ieee->seq_ctrl[0] == 0xFFF)
2292 ieee->seq_ctrl[0] = 0;
2293 else
2294 ieee->seq_ctrl[0]++;
2295
2296 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
2297 }
2298 }
2299 if (!ieee->queue_stop && ieee->tx_pending.txb)
2300 ieee80211_resume_tx(ieee);
2301
2302 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2303 ieee->softmac_stats.swtxawake++;
2304 netif_wake_queue(ieee->dev);
2305 }
2306
2307exit :
2308 spin_unlock_irqrestore(&ieee->lock,flags);
2309}
2310
2311
2312void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2313{
2314 if (! netif_queue_stopped(ieee->dev)){
2315 netif_stop_queue(ieee->dev);
2316 ieee->softmac_stats.swtxstop++;
2317 }
2318 ieee->queue_stop = 1;
2319}
2320
2321
2322inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2323{
2324
2325 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2326
2327 /* an IBSS cell address must have the two less significant
2328 * bits of the first byte = 2
2329 */
2330 ieee->current_network.bssid[0] &= ~0x01;
2331 ieee->current_network.bssid[0] |= 0x02;
2332}
2333
2334/* called in user context only */
2335void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2336{
2337 ieee->assoc_id = 1;
2338
2339 if (ieee->current_network.ssid_len == 0){
2340 strncpy(ieee->current_network.ssid,
2341 IEEE80211_DEFAULT_TX_ESSID,
2342 IW_ESSID_MAX_SIZE);
2343
2344 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2345 ieee->ssid_set = 1;
2346 }
2347
2348 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2349
2350 ieee->set_chan(ieee, ieee->current_network.channel);
2351 ieee->state = IEEE80211_LINKED;
2352 ieee->link_change(ieee);
2353 notify_wx_assoc_event(ieee);
2354
2355 if (ieee->data_hard_resume)
2356 ieee->data_hard_resume(ieee);
2357
2358 netif_carrier_on(ieee->dev);
2359}
2360
2361void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2362{
2363 if(ieee->raw_tx){
2364
2365 if (ieee->data_hard_resume)
2366 ieee->data_hard_resume(ieee);
2367
2368 netif_carrier_on(ieee->dev);
2369 }
2370}
2371void ieee80211_start_ibss_wq(struct work_struct *work)
2372{
2373
2374 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2375 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2376 /* iwconfig mode ad-hoc will schedule this and return
2377 * on the other hand this will block further iwconfig SET
2378 * operations because of the wx_sem hold.
2379 * Anyway some most set operations set a flag to speed-up
2380 * (abort) this wq (when syncro scanning) before sleeping
2381 * on the semaphore
2382 */
2383 if(!ieee->proto_started){
2384 printk("==========oh driver down return\n");
2385 return;
2386 }
2387 down(&ieee->wx_sem);
2388
2389 if (ieee->current_network.ssid_len == 0){
2390 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2391 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2392 ieee->ssid_set = 1;
2393 }
2394
2395 ieee->state = IEEE80211_NOLINK;
2396 /* check if we have this cell in our network list */
2397 ieee80211_softmac_check_all_nets(ieee);
2398
2399
2400#ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
2401 if (ieee->state == IEEE80211_NOLINK)
2402 ieee->current_network.channel = 6;
2403#endif
2404 /* if not then the state is not linked. Maybe the user swithced to
2405 * ad-hoc mode just after being in monitor mode, or just after
2406 * being very few time in managed mode (so the card have had no
2407 * time to scan all the chans..) or we have just run up the iface
2408 * after setting ad-hoc mode. So we have to give another try..
2409 * Here, in ibss mode, should be safe to do this without extra care
2410 * (in bss mode we had to make sure no-one tryed to associate when
2411 * we had just checked the ieee->state and we was going to start the
2412 * scan) beacause in ibss mode the ieee80211_new_net function, when
2413 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2414 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2415 * scan, that will stop at the first round because it sees the state
2416 * associated.
2417 */
2418 if (ieee->state == IEEE80211_NOLINK)
2419 ieee80211_start_scan_syncro(ieee);
2420
2421 /* the network definitively is not here.. create a new cell */
2422 if (ieee->state == IEEE80211_NOLINK){
2423 printk("creating new IBSS cell\n");
2424 if(!ieee->wap_set)
2425 ieee80211_randomize_cell(ieee);
2426
2427 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2428
2429 ieee->current_network.rates_len = 4;
2430
2431 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2432 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2433 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2434 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2435
2436 }else
2437 ieee->current_network.rates_len = 0;
2438
2439 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2440 ieee->current_network.rates_ex_len = 8;
2441
2442 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2443 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2444 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2445 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2446 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2447 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2448 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2449 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2450
2451 ieee->rate = 108;
2452 }else{
2453 ieee->current_network.rates_ex_len = 0;
2454 ieee->rate = 22;
2455 }
2456
2457 // By default, WMM function will be disabled in IBSS mode
2458 ieee->current_network.QoS_Enable = 0;
2459 ieee->SetWirelessMode(ieee, IEEE_G);
2460 ieee->current_network.atim_window = 0;
2461 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2462 if(ieee->short_slot)
2463 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2464
2465 }
2466
2467 ieee->state = IEEE80211_LINKED;
2468
2469 ieee->set_chan(ieee, ieee->current_network.channel);
2470 ieee->link_change(ieee);
2471
2472 notify_wx_assoc_event(ieee);
2473
2474 ieee80211_start_send_beacons(ieee);
2475
2476 if (ieee->data_hard_resume)
2477 ieee->data_hard_resume(ieee);
2478 netif_carrier_on(ieee->dev);
2479
2480 up(&ieee->wx_sem);
2481}
2482
2483inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2484{
2485 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2486}
2487
2488/* this is called only in user context, with wx_sem held */
2489void ieee80211_start_bss(struct ieee80211_device *ieee)
2490{
2491 unsigned long flags;
2492#ifdef ENABLE_DOT11D
2493 //
2494 // Ref: 802.11d 11.1.3.3
2495 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2496 //
2497 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2498 {
2499 if(! ieee->bGlobalDomain)
2500 {
2501 return;
2502 }
2503 }
2504#endif
2505 /* check if we have already found the net we
2506 * are interested in (if any).
2507 * if not (we are disassociated and we are not
2508 * in associating / authenticating phase) start the background scanning.
2509 */
2510 ieee80211_softmac_check_all_nets(ieee);
2511
2512 /* ensure no-one start an associating process (thus setting
2513 * the ieee->state to ieee80211_ASSOCIATING) while we
2514 * have just cheked it and we are going to enable scan.
2515 * The ieee80211_new_net function is always called with
2516 * lock held (from both ieee80211_softmac_check_all_nets and
2517 * the rx path), so we cannot be in the middle of such function
2518 */
2519 spin_lock_irqsave(&ieee->lock, flags);
2520
2521 if (ieee->state == IEEE80211_NOLINK){
2522#ifdef ENABLE_IPS
2523 if(ieee->ieee80211_ips_leave_wq != NULL)
2524 ieee->ieee80211_ips_leave_wq(ieee);
2525#endif
2526 ieee->actscanning = true;
2527 ieee80211_rtl_start_scan(ieee);
2528 }
2529 spin_unlock_irqrestore(&ieee->lock, flags);
2530}
2531
2532/* called only in userspace context */
2533void ieee80211_disassociate(struct ieee80211_device *ieee)
2534{
2535
2536
2537 netif_carrier_off(ieee->dev);
2538 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2539 ieee80211_reset_queue(ieee);
2540
2541 if (ieee->data_hard_stop)
2542 ieee->data_hard_stop(ieee);
2543#ifdef ENABLE_DOT11D
2544 if(IS_DOT11D_ENABLE(ieee))
2545 Dot11d_Reset(ieee);
2546#endif
2547 ieee->is_set_key = false;
2548 ieee->link_change(ieee);
2549 if (ieee->state == IEEE80211_LINKED ||
2550 ieee->state == IEEE80211_ASSOCIATING) {
2551 ieee->state = IEEE80211_NOLINK;
2552 notify_wx_assoc_event(ieee);
2553 }
2554
2555 ieee->state = IEEE80211_NOLINK;
2556
2557}
2558void ieee80211_associate_retry_wq(struct work_struct *work)
2559{
2560 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2561 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2562 unsigned long flags;
2563
2564 down(&ieee->wx_sem);
2565 if(!ieee->proto_started)
2566 goto exit;
2567
2568 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2569 goto exit;
2570
2571 /* until we do not set the state to IEEE80211_NOLINK
2572 * there are no possibility to have someone else trying
2573 * to start an association procdure (we get here with
2574 * ieee->state = IEEE80211_ASSOCIATING).
2575 * When we set the state to IEEE80211_NOLINK it is possible
2576 * that the RX path run an attempt to associate, but
2577 * both ieee80211_softmac_check_all_nets and the
2578 * RX path works with ieee->lock held so there are no
2579 * problems. If we are still disassociated then start a scan.
2580 * the lock here is necessary to ensure no one try to start
2581 * an association procedure when we have just checked the
2582 * state and we are going to start the scan.
2583 */
2584 ieee->beinretry = true;
2585 ieee->state = IEEE80211_NOLINK;
2586
2587 ieee80211_softmac_check_all_nets(ieee);
2588
2589 spin_lock_irqsave(&ieee->lock, flags);
2590
2591 if(ieee->state == IEEE80211_NOLINK)
2592 {
2593 ieee->is_roaming= false;
2594 ieee->actscanning = true;
2595 ieee80211_rtl_start_scan(ieee);
2596 }
2597 spin_unlock_irqrestore(&ieee->lock, flags);
2598
2599 ieee->beinretry = false;
2600exit:
2601 up(&ieee->wx_sem);
2602}
2603
2604struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2605{
2606 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2607
2608 struct sk_buff *skb;
2609 struct ieee80211_probe_response *b;
2610
2611 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2612
2613 if (!skb)
2614 return NULL;
2615
2616 b = (struct ieee80211_probe_response *) skb->data;
2617 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2618
2619 return skb;
2620
2621}
2622
2623struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2624{
2625 struct sk_buff *skb;
2626 struct ieee80211_probe_response *b;
2627
2628 skb = ieee80211_get_beacon_(ieee);
2629 if(!skb)
2630 return NULL;
2631
2632 b = (struct ieee80211_probe_response *) skb->data;
2633 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2634
2635 if (ieee->seq_ctrl[0] == 0xFFF)
2636 ieee->seq_ctrl[0] = 0;
2637 else
2638 ieee->seq_ctrl[0]++;
2639
2640 return skb;
2641}
2642
2643void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2644{
2645 ieee->sync_scan_hurryup = 1;
2646 down(&ieee->wx_sem);
2647 ieee80211_stop_protocol(ieee, shutdown);
2648 up(&ieee->wx_sem);
2649}
2650
2651
2652void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2653{
2654 if (!ieee->proto_started)
2655 return;
2656
2657 if(shutdown)
2658 ieee->proto_started = 0;
2659 ieee->proto_stoppping = 1;
2660
2661 ieee80211_stop_send_beacons(ieee);
2662 del_timer_sync(&ieee->associate_timer);
2663 cancel_delayed_work(&ieee->associate_retry_wq);
2664 cancel_delayed_work(&ieee->start_ibss_wq);
2665 ieee80211_stop_scan(ieee);
2666
2667 ieee80211_disassociate(ieee);
2668 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2669
2670 ieee->proto_stoppping = 0;
2671}
2672
2673void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2674{
2675 ieee->sync_scan_hurryup = 0;
2676 down(&ieee->wx_sem);
2677 ieee80211_start_protocol(ieee);
2678 up(&ieee->wx_sem);
2679}
2680
2681void ieee80211_start_protocol(struct ieee80211_device *ieee)
2682{
2683 short ch = 0;
2684 int i = 0;
2685 if (ieee->proto_started)
2686 return;
2687
2688 ieee->proto_started = 1;
2689
2690 if (ieee->current_network.channel == 0){
2691 do{
2692 ch++;
2693 if (ch > MAX_CHANNEL_NUMBER)
2694 return; /* no channel found */
2695#ifdef ENABLE_DOT11D
2696 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2697#else
2698 }while(!ieee->channel_map[ch]);
2699#endif
2700 ieee->current_network.channel = ch;
2701 }
2702
2703 if (ieee->current_network.beacon_interval == 0)
2704 ieee->current_network.beacon_interval = 100;
2705
2706 for(i = 0; i < 17; i++) {
2707 ieee->last_rxseq_num[i] = -1;
2708 ieee->last_rxfrag_num[i] = -1;
2709 ieee->last_packet_time[i] = 0;
2710 }
2711
2712 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2713
2714 ieee->state = IEEE80211_NOLINK;
2715
2716
2717 /* if the user set the MAC of the ad-hoc cell and then
2718 * switch to managed mode, shall we make sure that association
2719 * attempts does not fail just because the user provide the essid
2720 * and the nic is still checking for the AP MAC ??
2721 */
2722 if (ieee->iw_mode == IW_MODE_INFRA)
2723 ieee80211_start_bss(ieee);
2724
2725 else if (ieee->iw_mode == IW_MODE_ADHOC)
2726 ieee80211_start_ibss(ieee);
2727
2728 else if (ieee->iw_mode == IW_MODE_MASTER)
2729 ieee80211_start_master_bss(ieee);
2730
2731 else if(ieee->iw_mode == IW_MODE_MONITOR)
2732 ieee80211_start_monitor_mode(ieee);
2733}
2734
2735
2736#define DRV_NAME "Ieee80211"
2737void ieee80211_softmac_init(struct ieee80211_device *ieee)
2738{
2739 int i;
2740 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2741
2742 ieee->state = IEEE80211_NOLINK;
2743 ieee->sync_scan_hurryup = 0;
2744 for(i = 0; i < 5; i++) {
2745 ieee->seq_ctrl[i] = 0;
2746 }
2747#ifdef ENABLE_DOT11D
2748 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2749 if (!ieee->pDot11dInfo)
2750 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2751#endif
2752 //added for AP roaming
2753 ieee->LinkDetectInfo.SlotNum = 2;
2754 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2755 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2756
2757 ieee->assoc_id = 0;
2758 ieee->queue_stop = 0;
2759 ieee->scanning = 0;
2760 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2761 ieee->wap_set = 0;
2762 ieee->ssid_set = 0;
2763 ieee->proto_started = 0;
2764 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2765 ieee->rate = 22;
2766 ieee->ps = IEEE80211_PS_DISABLED;
2767 ieee->sta_sleep = 0;
2768 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2769 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2770 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2771 //added by amy
2772 ieee->actscanning = false;
2773 ieee->beinretry = false;
2774 ieee->is_set_key = false;
2775 init_mgmt_queue(ieee);
2776
2777 ieee->sta_edca_param[0] = 0x0000A403;
2778 ieee->sta_edca_param[1] = 0x0000A427;
2779 ieee->sta_edca_param[2] = 0x005E4342;
2780 ieee->sta_edca_param[3] = 0x002F3262;
2781 ieee->aggregation = true;
2782 ieee->enable_rx_imm_BA = 1;
2783 ieee->tx_pending.txb = NULL;
2784
2785 init_timer(&ieee->associate_timer);
2786 ieee->associate_timer.data = (unsigned long)ieee;
2787 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2788
2789 init_timer(&ieee->beacon_timer);
2790 ieee->beacon_timer.data = (unsigned long) ieee;
2791 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2792
2793 ieee->wq = create_workqueue(DRV_NAME);
2794
2795 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2796 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2797 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2798 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2799 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2800 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2801
2802 sema_init(&ieee->wx_sem, 1);
2803 sema_init(&ieee->scan_sem, 1);
2804#ifdef ENABLE_IPS
2805 sema_init(&ieee->ips_sem,1);
2806#endif
2807 spin_lock_init(&ieee->mgmt_tx_lock);
2808 spin_lock_init(&ieee->beacon_lock);
2809
2810 tasklet_init(&ieee->ps_task,
2811 (void(*)(unsigned long)) ieee80211_sta_ps,
2812 (unsigned long)ieee);
2813
2814}
2815
2816void ieee80211_softmac_free(struct ieee80211_device *ieee)
2817{
2818 down(&ieee->wx_sem);
2819#ifdef ENABLE_DOT11D
2820 kfree(ieee->pDot11dInfo);
2821 ieee->pDot11dInfo = NULL;
2822#endif
2823 del_timer_sync(&ieee->associate_timer);
2824
2825 cancel_delayed_work(&ieee->associate_retry_wq);
2826 destroy_workqueue(ieee->wq);
2827
2828 up(&ieee->wx_sem);
2829}
2830
2831/********************************************************
2832 * Start of WPA code. *
2833 * this is stolen from the ipw2200 driver *
2834 ********************************************************/
2835
2836
2837static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2838{
2839 /* This is called when wpa_supplicant loads and closes the driver
2840 * interface. */
2841 printk("%s WPA\n",value ? "enabling" : "disabling");
2842 ieee->wpa_enabled = value;
2843 return 0;
2844}
2845
2846
2847void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2848{
2849 /* make sure WPA is enabled */
2850 ieee80211_wpa_enable(ieee, 1);
2851
2852 ieee80211_disassociate(ieee);
2853}
2854
2855
2856static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2857{
2858
2859 int ret = 0;
2860
2861 switch (command) {
2862 case IEEE_MLME_STA_DEAUTH:
2863 // silently ignore
2864 break;
2865
2866 case IEEE_MLME_STA_DISASSOC:
2867 ieee80211_disassociate(ieee);
2868 break;
2869
2870 default:
2871 printk("Unknown MLME request: %d\n", command);
2872 ret = -EOPNOTSUPP;
2873 }
2874
2875 return ret;
2876}
2877
2878
2879static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2880 struct ieee_param *param, int plen)
2881{
2882 u8 *buf;
2883
2884 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2885 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2886 return -EINVAL;
2887
2888 if (param->u.wpa_ie.len) {
2889 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2890 GFP_KERNEL);
2891 if (buf == NULL)
2892 return -ENOMEM;
2893
2894 kfree(ieee->wpa_ie);
2895 ieee->wpa_ie = buf;
2896 ieee->wpa_ie_len = param->u.wpa_ie.len;
2897 } else {
2898 kfree(ieee->wpa_ie);
2899 ieee->wpa_ie = NULL;
2900 ieee->wpa_ie_len = 0;
2901 }
2902
2903 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2904 return 0;
2905}
2906
2907#define AUTH_ALG_OPEN_SYSTEM 0x1
2908#define AUTH_ALG_SHARED_KEY 0x2
2909
2910static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2911{
2912
2913 struct ieee80211_security sec = {
2914 .flags = SEC_AUTH_MODE,
2915 };
2916 int ret = 0;
2917
2918 if (value & AUTH_ALG_SHARED_KEY) {
2919 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2920 ieee->open_wep = 0;
2921 ieee->auth_mode = 1;
2922 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2923 sec.auth_mode = WLAN_AUTH_OPEN;
2924 ieee->open_wep = 1;
2925 ieee->auth_mode = 0;
2926 }
2927 else if (value & IW_AUTH_ALG_LEAP){
2928 sec.auth_mode = WLAN_AUTH_LEAP;
2929 ieee->open_wep = 1;
2930 ieee->auth_mode = 2;
2931 }
2932
2933
2934 if (ieee->set_security)
2935 ieee->set_security(ieee, &sec);
2936
2937 return ret;
2938}
2939
2940static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2941{
2942 int ret=0;
2943 unsigned long flags;
2944
2945 switch (name) {
2946 case IEEE_PARAM_WPA_ENABLED:
2947 ret = ieee80211_wpa_enable(ieee, value);
2948 break;
2949
2950 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2951 ieee->tkip_countermeasures=value;
2952 break;
2953
2954 case IEEE_PARAM_DROP_UNENCRYPTED: {
2955 /* HACK:
2956 *
2957 * wpa_supplicant calls set_wpa_enabled when the driver
2958 * is loaded and unloaded, regardless of if WPA is being
2959 * used. No other calls are made which can be used to
2960 * determine if encryption will be used or not prior to
2961 * association being expected. If encryption is not being
2962 * used, drop_unencrypted is set to false, else true -- we
2963 * can use this to determine if the CAP_PRIVACY_ON bit should
2964 * be set.
2965 */
2966 struct ieee80211_security sec = {
2967 .flags = SEC_ENABLED,
2968 .enabled = value,
2969 };
2970 ieee->drop_unencrypted = value;
2971 /* We only change SEC_LEVEL for open mode. Others
2972 * are set by ipw_wpa_set_encryption.
2973 */
2974 if (!value) {
2975 sec.flags |= SEC_LEVEL;
2976 sec.level = SEC_LEVEL_0;
2977 }
2978 else {
2979 sec.flags |= SEC_LEVEL;
2980 sec.level = SEC_LEVEL_1;
2981 }
2982 if (ieee->set_security)
2983 ieee->set_security(ieee, &sec);
2984 break;
2985 }
2986
2987 case IEEE_PARAM_PRIVACY_INVOKED:
2988 ieee->privacy_invoked=value;
2989 break;
2990
2991 case IEEE_PARAM_AUTH_ALGS:
2992 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2993 break;
2994
2995 case IEEE_PARAM_IEEE_802_1X:
2996 ieee->ieee802_1x=value;
2997 break;
2998 case IEEE_PARAM_WPAX_SELECT:
2999 // added for WPA2 mixed mode
3000 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3001 ieee->wpax_type_set = 1;
3002 ieee->wpax_type_notify = value;
3003 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3004 break;
3005
3006 default:
3007 printk("Unknown WPA param: %d\n",name);
3008 ret = -EOPNOTSUPP;
3009 }
3010
3011 return ret;
3012}
3013
3014/* implementation borrowed from hostap driver */
3015
3016static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3017 struct ieee_param *param, int param_len)
3018{
3019 int ret = 0;
3020
3021 struct ieee80211_crypto_ops *ops;
3022 struct ieee80211_crypt_data **crypt;
3023
3024 struct ieee80211_security sec = {
3025 .flags = 0,
3026 };
3027
3028 param->u.crypt.err = 0;
3029 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3030
3031 if (param_len !=
3032 (int) ((char *) param->u.crypt.key - (char *) param) +
3033 param->u.crypt.key_len) {
3034 printk("Len mismatch %d, %d\n", param_len,
3035 param->u.crypt.key_len);
3036 return -EINVAL;
3037 }
3038 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3039 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3040 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3041 if (param->u.crypt.idx >= WEP_KEYS)
3042 return -EINVAL;
3043 crypt = &ieee->crypt[param->u.crypt.idx];
3044 } else {
3045 return -EINVAL;
3046 }
3047
3048 if (strcmp(param->u.crypt.alg, "none") == 0) {
3049 if (crypt) {
3050 sec.enabled = 0;
3051 // FIXME FIXME
3052 //sec.encrypt = 0;
3053 sec.level = SEC_LEVEL_0;
3054 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3055 ieee80211_crypt_delayed_deinit(ieee, crypt);
3056 }
3057 goto done;
3058 }
3059 sec.enabled = 1;
3060// FIXME FIXME
3061// sec.encrypt = 1;
3062 sec.flags |= SEC_ENABLED;
3063
3064 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3065 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3066 strcmp(param->u.crypt.alg, "TKIP"))
3067 goto skip_host_crypt;
3068
3069 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3070 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3071 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3072 /* set WEP40 first, it will be modified according to WEP104 or
3073 * WEP40 at other place */
3074 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3075 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3076 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3077 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3078 if (ops == NULL) {
3079 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3080 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3081 ret = -EINVAL;
3082 goto done;
3083 }
3084
3085 if (*crypt == NULL || (*crypt)->ops != ops) {
3086 struct ieee80211_crypt_data *new_crypt;
3087
3088 ieee80211_crypt_delayed_deinit(ieee, crypt);
3089
3090 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3091 if (new_crypt == NULL) {
3092 ret = -ENOMEM;
3093 goto done;
3094 }
3095 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3096 new_crypt->ops = ops;
3097 if (new_crypt->ops)
3098 new_crypt->priv =
3099 new_crypt->ops->init(param->u.crypt.idx);
3100
3101 if (new_crypt->priv == NULL) {
3102 kfree(new_crypt);
3103 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3104 ret = -EINVAL;
3105 goto done;
3106 }
3107
3108 *crypt = new_crypt;
3109 }
3110
3111 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3112 (*crypt)->ops->set_key(param->u.crypt.key,
3113 param->u.crypt.key_len, param->u.crypt.seq,
3114 (*crypt)->priv) < 0) {
3115 printk("key setting failed\n");
3116 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3117 ret = -EINVAL;
3118 goto done;
3119 }
3120
3121 skip_host_crypt:
3122 if (param->u.crypt.set_tx) {
3123 ieee->tx_keyidx = param->u.crypt.idx;
3124 sec.active_key = param->u.crypt.idx;
3125 sec.flags |= SEC_ACTIVE_KEY;
3126 } else
3127 sec.flags &= ~SEC_ACTIVE_KEY;
3128
3129 if (param->u.crypt.alg != NULL) {
3130 memcpy(sec.keys[param->u.crypt.idx],
3131 param->u.crypt.key,
3132 param->u.crypt.key_len);
3133 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3134 sec.flags |= (1 << param->u.crypt.idx);
3135
3136 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3137 sec.flags |= SEC_LEVEL;
3138 sec.level = SEC_LEVEL_1;
3139 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3140 sec.flags |= SEC_LEVEL;
3141 sec.level = SEC_LEVEL_2;
3142 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3143 sec.flags |= SEC_LEVEL;
3144 sec.level = SEC_LEVEL_3;
3145 }
3146 }
3147 done:
3148 if (ieee->set_security)
3149 ieee->set_security(ieee, &sec);
3150
3151 /* Do not reset port if card is in Managed mode since resetting will
3152 * generate new IEEE 802.11 authentication which may end up in looping
3153 * with IEEE 802.1X. If your hardware requires a reset after WEP
3154 * configuration (for example... Prism2), implement the reset_port in
3155 * the callbacks structures used to initialize the 802.11 stack. */
3156 if (ieee->reset_on_keychange &&
3157 ieee->iw_mode != IW_MODE_INFRA &&
3158 ieee->reset_port &&
3159 ieee->reset_port(ieee)) {
3160 printk("reset_port failed\n");
3161 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3162 return -EINVAL;
3163 }
3164
3165 return ret;
3166}
3167
3168inline struct sk_buff *ieee80211_disassociate_skb(
3169 struct ieee80211_network *beacon,
3170 struct ieee80211_device *ieee,
3171 u8 asRsn)
3172{
3173 struct sk_buff *skb;
3174 struct ieee80211_disassoc *disass;
3175
3176 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3177 if (!skb)
3178 return NULL;
3179
3180 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3181 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3182 disass->header.duration_id = 0;
3183
3184 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3185 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3186 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3187
3188 disass->reason = asRsn;
3189 return skb;
3190}
3191
3192
3193void
3194SendDisassociation(
3195 struct ieee80211_device *ieee,
3196 u8* asSta,
3197 u8 asRsn
3198)
3199{
3200 struct ieee80211_network *beacon = &ieee->current_network;
3201 struct sk_buff *skb;
3202 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3203 if (skb){
3204 softmac_mgmt_xmit(skb, ieee);
3205 //dev_kfree_skb_any(skb);//edit by thomas
3206 }
3207}
3208
3209int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3210{
3211 struct ieee_param *param;
3212 int ret=0;
3213
3214 down(&ieee->wx_sem);
3215 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3216
3217 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3218 ret = -EINVAL;
3219 goto out;
3220 }
3221
3222 param = kmalloc(p->length, GFP_KERNEL);
3223 if (param == NULL){
3224 ret = -ENOMEM;
3225 goto out;
3226 }
3227 if (copy_from_user(param, p->pointer, p->length)) {
3228 kfree(param);
3229 ret = -EFAULT;
3230 goto out;
3231 }
3232
3233 switch (param->cmd) {
3234
3235 case IEEE_CMD_SET_WPA_PARAM:
3236 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3237 param->u.wpa_param.value);
3238 break;
3239
3240 case IEEE_CMD_SET_WPA_IE:
3241 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3242 break;
3243
3244 case IEEE_CMD_SET_ENCRYPTION:
3245 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3246 break;
3247
3248 case IEEE_CMD_MLME:
3249 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3250 param->u.mlme.reason_code);
3251 break;
3252
3253 default:
3254 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3255 ret = -EOPNOTSUPP;
3256 break;
3257 }
3258
3259 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3260 ret = -EFAULT;
3261
3262 kfree(param);
3263out:
3264 up(&ieee->wx_sem);
3265
3266 return ret;
3267}
3268
3269void notify_wx_assoc_event(struct ieee80211_device *ieee)
3270{
3271 union iwreq_data wrqu;
3272 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3273 if (ieee->state == IEEE80211_LINKED)
3274 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3275 else
3276 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3277 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3278}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
new file mode 100644
index 00000000000..d8a068e32e5
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -0,0 +1,600 @@
1/* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Some pieces of code might be stolen from ipw2100 driver
8 * copyright of who own it's copyright ;-)
9 *
10 * PS wx handler mostly stolen from hostap, copyright who
11 * own it's copyright ;-)
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18#ifdef ENABLE_DOT11D
19#include "dot11d.h"
20#endif
21/* FIXME: add A freqs */
22
23const long ieee80211_wlan_frequencies[] = {
24 2412, 2417, 2422, 2427,
25 2432, 2437, 2442, 2447,
26 2452, 2457, 2462, 2467,
27 2472, 2484
28};
29
30
31int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
32 union iwreq_data *wrqu, char *b)
33{
34 int ret;
35 struct iw_freq *fwrq = & wrqu->freq;
36
37 down(&ieee->wx_sem);
38
39 if(ieee->iw_mode == IW_MODE_INFRA){
40 ret = -EOPNOTSUPP;
41 goto out;
42 }
43
44 /* if setting by freq convert to channel */
45 if (fwrq->e == 1) {
46 if ((fwrq->m >= (int) 2.412e8 &&
47 fwrq->m <= (int) 2.487e8)) {
48 int f = fwrq->m / 100000;
49 int c = 0;
50
51 while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
52 c++;
53
54 /* hack to fall through */
55 fwrq->e = 0;
56 fwrq->m = c + 1;
57 }
58 }
59
60 if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){
61 ret = -EOPNOTSUPP;
62 goto out;
63
64 }else { /* Set the channel */
65
66#ifdef ENABLE_DOT11D
67 if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) {
68 ret = -EINVAL;
69 goto out;
70 }
71#endif
72 ieee->current_network.channel = fwrq->m;
73 ieee->set_chan(ieee, ieee->current_network.channel);
74
75 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
76 if(ieee->state == IEEE80211_LINKED){
77
78 ieee80211_stop_send_beacons(ieee);
79 ieee80211_start_send_beacons(ieee);
80 }
81 }
82
83 ret = 0;
84out:
85 up(&ieee->wx_sem);
86 return ret;
87}
88
89
90int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
91 struct iw_request_info *a,
92 union iwreq_data *wrqu, char *b)
93{
94 struct iw_freq *fwrq = & wrqu->freq;
95
96 if (ieee->current_network.channel == 0)
97 return -1;
98 //NM 0.7.0 will not accept channel any more.
99 fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000;
100 fwrq->e = 1;
101
102 return 0;
103}
104
105int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
106 struct iw_request_info *info,
107 union iwreq_data *wrqu, char *extra)
108{
109 unsigned long flags;
110 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
111
112 if (ieee->iw_mode == IW_MODE_MONITOR)
113 return -1;
114
115 /* We want avoid to give to the user inconsistent infos*/
116 spin_lock_irqsave(&ieee->lock, flags);
117
118 if (ieee->state != IEEE80211_LINKED &&
119 ieee->state != IEEE80211_LINKED_SCANNING &&
120 ieee->wap_set == 0)
121
122 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
123 else
124 memcpy(wrqu->ap_addr.sa_data,
125 ieee->current_network.bssid, ETH_ALEN);
126
127 spin_unlock_irqrestore(&ieee->lock, flags);
128
129 return 0;
130}
131
132
133int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
134 struct iw_request_info *info,
135 union iwreq_data *awrq,
136 char *extra)
137{
138
139 int ret = 0;
140 u8 zero[] = {0,0,0,0,0,0};
141 unsigned long flags;
142
143 short ifup = ieee->proto_started;//dev->flags & IFF_UP;
144 struct sockaddr *temp = (struct sockaddr *)awrq;
145
146 ieee->sync_scan_hurryup = 1;
147
148 down(&ieee->wx_sem);
149 /* use ifconfig hw ether */
150 if (ieee->iw_mode == IW_MODE_MASTER){
151 ret = -1;
152 goto out;
153 }
154
155 if (temp->sa_family != ARPHRD_ETHER){
156 ret = -EINVAL;
157 goto out;
158 }
159
160 if (ifup)
161 ieee80211_stop_protocol(ieee,true);
162
163 /* just to avoid to give inconsistent infos in the
164 * get wx method. not really needed otherwise
165 */
166 spin_lock_irqsave(&ieee->lock, flags);
167
168 memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
169 ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0;
170
171 spin_unlock_irqrestore(&ieee->lock, flags);
172
173 if (ifup)
174 ieee80211_start_protocol(ieee);
175out:
176 up(&ieee->wx_sem);
177 return ret;
178}
179
180 int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
181{
182 int len,ret = 0;
183 unsigned long flags;
184
185 if (ieee->iw_mode == IW_MODE_MONITOR)
186 return -1;
187
188 /* We want avoid to give to the user inconsistent infos*/
189 spin_lock_irqsave(&ieee->lock, flags);
190
191 if (ieee->current_network.ssid[0] == '\0' ||
192 ieee->current_network.ssid_len == 0){
193 ret = -1;
194 goto out;
195 }
196
197 if (ieee->state != IEEE80211_LINKED &&
198 ieee->state != IEEE80211_LINKED_SCANNING &&
199 ieee->ssid_set == 0){
200 ret = -1;
201 goto out;
202 }
203 len = ieee->current_network.ssid_len;
204 wrqu->essid.length = len;
205 strncpy(b,ieee->current_network.ssid,len);
206 wrqu->essid.flags = 1;
207
208out:
209 spin_unlock_irqrestore(&ieee->lock, flags);
210
211 return ret;
212
213}
214
215int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
216 struct iw_request_info *info,
217 union iwreq_data *wrqu, char *extra)
218{
219
220 u32 target_rate = wrqu->bitrate.value;
221
222 ieee->rate = target_rate/100000;
223 //FIXME: we might want to limit rate also in management protocols.
224 return 0;
225}
226
227
228
229int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
230 struct iw_request_info *info,
231 union iwreq_data *wrqu, char *extra)
232{
233 u32 tmp_rate;
234 tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
235
236 wrqu->bitrate.value = tmp_rate * 500000;
237
238 return 0;
239}
240
241
242int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
243 struct iw_request_info *info,
244 union iwreq_data *wrqu, char *extra)
245{
246 if (wrqu->rts.disabled || !wrqu->rts.fixed)
247 ieee->rts = DEFAULT_RTS_THRESHOLD;
248 else
249 {
250 if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
251 wrqu->rts.value > MAX_RTS_THRESHOLD)
252 return -EINVAL;
253 ieee->rts = wrqu->rts.value;
254 }
255 return 0;
256}
257
258int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
259 struct iw_request_info *info,
260 union iwreq_data *wrqu, char *extra)
261{
262 wrqu->rts.value = ieee->rts;
263 wrqu->rts.fixed = 0; /* no auto select */
264 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
265 return 0;
266}
267int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
268 union iwreq_data *wrqu, char *b)
269{
270
271 ieee->sync_scan_hurryup = 1;
272
273 down(&ieee->wx_sem);
274
275 if (wrqu->mode == ieee->iw_mode)
276 goto out;
277
278 if (wrqu->mode == IW_MODE_MONITOR){
279
280 ieee->dev->type = ARPHRD_IEEE80211;
281 }else{
282 ieee->dev->type = ARPHRD_ETHER;
283 }
284
285 if (!ieee->proto_started){
286 ieee->iw_mode = wrqu->mode;
287 }else{
288 ieee80211_stop_protocol(ieee,true);
289 ieee->iw_mode = wrqu->mode;
290 ieee80211_start_protocol(ieee);
291 }
292
293out:
294 up(&ieee->wx_sem);
295 return 0;
296}
297
298void ieee80211_wx_sync_scan_wq(struct work_struct *work)
299{
300 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
301 short chan;
302 HT_EXTCHNL_OFFSET chan_offset=0;
303 HT_CHANNEL_WIDTH bandwidth=0;
304 int b40M = 0;
305 static int count = 0;
306 chan = ieee->current_network.channel;
307
308#ifdef ENABLE_LPS
309 if (ieee->LeisurePSLeave) {
310 ieee->LeisurePSLeave(ieee);
311 }
312
313 /* notify AP to be in PS mode */
314 ieee80211_sta_ps_send_null_frame(ieee, 1);
315 ieee80211_sta_ps_send_null_frame(ieee, 1);
316#endif
317
318 if (ieee->data_hard_stop)
319 ieee->data_hard_stop(ieee);
320
321 ieee80211_stop_send_beacons(ieee);
322
323 ieee->state = IEEE80211_LINKED_SCANNING;
324 ieee->link_change(ieee);
325 ieee->InitialGainHandler(ieee, IG_Backup);
326 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
327 b40M = 1;
328 chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
329 bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
330 printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
331 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
332 }
333 ieee80211_start_scan_syncro(ieee);
334 if (b40M) {
335 printk("Scan in 20M, back to 40M\n");
336 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
337 ieee->set_chan(ieee, chan + 2);
338 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
339 ieee->set_chan(ieee, chan - 2);
340 else
341 ieee->set_chan(ieee, chan);
342 ieee->SetBWModeHandler(ieee, bandwidth, chan_offset);
343 } else {
344 ieee->set_chan(ieee, chan);
345 }
346
347 ieee->InitialGainHandler(ieee, IG_Restore);
348 ieee->state = IEEE80211_LINKED;
349 ieee->link_change(ieee);
350
351#ifdef ENABLE_LPS
352 /* Notify AP that I wake up again */
353 ieee80211_sta_ps_send_null_frame(ieee, 0);
354#endif
355
356 // To prevent the immediately calling watch_dog after scan.
357 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
358 {
359 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
360 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
361 }
362 if (ieee->data_hard_resume)
363 ieee->data_hard_resume(ieee);
364
365 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
366 ieee80211_start_send_beacons(ieee);
367
368 count = 0;
369 up(&ieee->wx_sem);
370
371}
372
373int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
374 union iwreq_data *wrqu, char *b)
375{
376 int ret = 0;
377
378 down(&ieee->wx_sem);
379
380 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
381 ret = -1;
382 goto out;
383 }
384
385 if ( ieee->state == IEEE80211_LINKED){
386 queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
387 /* intentionally forget to up sem */
388 return 0;
389 }
390
391out:
392 up(&ieee->wx_sem);
393 return ret;
394}
395
396int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
397 struct iw_request_info *a,
398 union iwreq_data *wrqu, char *extra)
399{
400
401 int ret=0,len;
402 short proto_started;
403 unsigned long flags;
404
405 ieee->sync_scan_hurryup = 1;
406 down(&ieee->wx_sem);
407
408 proto_started = ieee->proto_started;
409
410 if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
411 ret= -E2BIG;
412 goto out;
413 }
414
415 if (ieee->iw_mode == IW_MODE_MONITOR){
416 ret= -1;
417 goto out;
418 }
419
420 if(proto_started){
421 ieee80211_stop_protocol(ieee,true);
422 }
423
424
425 /* this is just to be sure that the GET wx callback
426 * has consisten infos. not needed otherwise
427 */
428 spin_lock_irqsave(&ieee->lock, flags);
429
430 if (wrqu->essid.flags && wrqu->essid.length) {
431 //first flush current network.ssid
432 len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
433 strncpy(ieee->current_network.ssid, extra, len+1);
434 ieee->current_network.ssid_len = len+1;
435 ieee->ssid_set = 1;
436 }
437 else{
438 ieee->ssid_set = 0;
439 ieee->current_network.ssid[0] = '\0';
440 ieee->current_network.ssid_len = 0;
441 }
442 spin_unlock_irqrestore(&ieee->lock, flags);
443
444 if (proto_started)
445 ieee80211_start_protocol(ieee);
446out:
447 up(&ieee->wx_sem);
448 return ret;
449}
450
451 int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
452 union iwreq_data *wrqu, char *b)
453{
454
455 wrqu->mode = ieee->iw_mode;
456 return 0;
457}
458
459 int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
460 struct iw_request_info *info,
461 union iwreq_data *wrqu, char *extra)
462{
463
464 int *parms = (int *)extra;
465 int enable = (parms[0] > 0);
466 short prev = ieee->raw_tx;
467
468 down(&ieee->wx_sem);
469
470 if(enable)
471 ieee->raw_tx = 1;
472 else
473 ieee->raw_tx = 0;
474
475 printk(KERN_INFO"raw TX is %s\n",
476 ieee->raw_tx ? "enabled" : "disabled");
477
478 if(ieee->iw_mode == IW_MODE_MONITOR)
479 {
480 if(prev == 0 && ieee->raw_tx){
481 if (ieee->data_hard_resume)
482 ieee->data_hard_resume(ieee);
483
484 netif_carrier_on(ieee->dev);
485 }
486
487 if(prev && ieee->raw_tx == 1)
488 netif_carrier_off(ieee->dev);
489 }
490
491 up(&ieee->wx_sem);
492
493 return 0;
494}
495
496int ieee80211_wx_get_name(struct ieee80211_device *ieee,
497 struct iw_request_info *info,
498 union iwreq_data *wrqu, char *extra)
499{
500 strcpy(wrqu->name, "802.11");
501 if(ieee->modulation & IEEE80211_CCK_MODULATION)
502 strcat(wrqu->name, "b");
503 if(ieee->modulation & IEEE80211_OFDM_MODULATION)
504 strcat(wrqu->name, "g");
505 if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
506 strcat(wrqu->name, "n");
507 return 0;
508}
509
510
511/* this is mostly stolen from hostap */
512int ieee80211_wx_set_power(struct ieee80211_device *ieee,
513 struct iw_request_info *info,
514 union iwreq_data *wrqu, char *extra)
515{
516 int ret = 0;
517
518 if(
519 (!ieee->sta_wake_up) ||
520 (!ieee->enter_sleep_state) ||
521 (!ieee->ps_is_queue_empty)){
522
523 return -1;
524 }
525
526 down(&ieee->wx_sem);
527
528 if (wrqu->power.disabled){
529 ieee->ps = IEEE80211_PS_DISABLED;
530 goto exit;
531 }
532 if (wrqu->power.flags & IW_POWER_TIMEOUT) {
533 ieee->ps_timeout = wrqu->power.value / 1000;
534 }
535
536 if (wrqu->power.flags & IW_POWER_PERIOD) {
537 ieee->ps_period = wrqu->power.value / 1000;
538 }
539 switch (wrqu->power.flags & IW_POWER_MODE) {
540 case IW_POWER_UNICAST_R:
541 ieee->ps = IEEE80211_PS_UNICAST;
542 break;
543 case IW_POWER_MULTICAST_R:
544 ieee->ps = IEEE80211_PS_MBCAST;
545 break;
546 case IW_POWER_ALL_R:
547 ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
548 break;
549
550 case IW_POWER_ON:
551 break;
552
553 default:
554 ret = -EINVAL;
555 goto exit;
556
557 }
558exit:
559 up(&ieee->wx_sem);
560 return ret;
561
562}
563
564/* this is stolen from hostap */
565int ieee80211_wx_get_power(struct ieee80211_device *ieee,
566 struct iw_request_info *info,
567 union iwreq_data *wrqu, char *extra)
568{
569 int ret =0;
570
571 down(&ieee->wx_sem);
572
573 if(ieee->ps == IEEE80211_PS_DISABLED){
574 wrqu->power.disabled = 1;
575 goto exit;
576 }
577
578 wrqu->power.disabled = 0;
579
580 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
581 wrqu->power.flags = IW_POWER_TIMEOUT;
582 wrqu->power.value = ieee->ps_timeout * 1000;
583 } else {
584 wrqu->power.flags = IW_POWER_PERIOD;
585 wrqu->power.value = ieee->ps_period * 1000;
586 }
587
588 if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST))
589 wrqu->power.flags |= IW_POWER_ALL_R;
590 else if (ieee->ps & IEEE80211_PS_MBCAST)
591 wrqu->power.flags |= IW_POWER_MULTICAST_R;
592 else
593 wrqu->power.flags |= IW_POWER_UNICAST_R;
594
595exit:
596 up(&ieee->wx_sem);
597 return ret;
598
599}
600
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
new file mode 100644
index 00000000000..424dd48da66
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -0,0 +1,955 @@
1/******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************
26
27 Few modifications for Realtek's Wi-Fi drivers by
28 Andrea Merello <andreamrl@tiscali.it>
29
30 A special thanks goes to Realtek for their support !
31
32******************************************************************************/
33
34#include <linux/compiler.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
43#include <linux/pci.h>
44#include <linux/proc_fs.h>
45#include <linux/skbuff.h>
46#include <linux/slab.h>
47#include <linux/tcp.h>
48#include <linux/types.h>
49#include <linux/wireless.h>
50#include <linux/etherdevice.h>
51#include <asm/uaccess.h>
52#include <linux/if_vlan.h>
53
54#include "ieee80211.h"
55
56
57/*
58
59
60802.11 Data Frame
61
62
63802.11 frame_contorl for data frames - 2 bytes
64 ,-----------------------------------------------------------------------------------------.
65bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
66 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
67val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
68 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
69desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
70 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
71 '-----------------------------------------------------------------------------------------'
72 /\
73 |
74802.11 Data Frame |
75 ,--------- 'ctrl' expands to >-----------'
76 |
77 ,--'---,-------------------------------------------------------------.
78Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
79 |------|------|---------|---------|---------|------|---------|------|
80Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
81 | | tion | (BSSID) | | | ence | data | |
82 `--------------------------------------------------| |------'
83Total: 28 non-data bytes `----.----'
84 |
85 .- 'Frame data' expands to <---------------------------'
86 |
87 V
88 ,---------------------------------------------------.
89Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
90 |------|------|---------|----------|------|---------|
91Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
92 | DSAP | SSAP | | | | Packet |
93 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
94 `-----------------------------------------| |
95Total: 8 non-data bytes `----.----'
96 |
97 .- 'IP Packet' expands, if WEP enabled, to <--'
98 |
99 V
100 ,-----------------------.
101Bytes | 4 | 0-2296 | 4 |
102 |-----|-----------|-----|
103Desc. | IV | Encrypted | ICV |
104 | | IP Packet | |
105 `-----------------------'
106Total: 8 non-data bytes
107
108
109802.3 Ethernet Data Frame
110
111 ,-----------------------------------------.
112Bytes | 6 | 6 | 2 | Variable | 4 |
113 |-------|-------|------|-----------|------|
114Desc. | Dest. | Source| Type | IP Packet | fcs |
115 | MAC | MAC | | | |
116 `-----------------------------------------'
117Total: 18 non-data bytes
118
119In the event that fragmentation is required, the incoming payload is split into
120N parts of size ieee->fts. The first fragment contains the SNAP header and the
121remaining packets are just data.
122
123If encryption is enabled, each fragment payload size is reduced by enough space
124to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
125So if you have 1500 bytes of payload with ieee->fts set to 500 without
126encryption it will take 3 frames. With WEP it will take 4 frames as the
127payload of each frame is reduced to 492 bytes.
128
129* SKB visualization
130*
131* ,- skb->data
132* |
133* | ETHERNET HEADER ,-<-- PAYLOAD
134* | | 14 bytes from skb->data
135* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
136* | | | |
137* |,-Dest.--. ,--Src.---. | | |
138* | 6 bytes| | 6 bytes | | | |
139* v | | | | | |
140* 0 | v 1 | v | v 2
141* 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
142* ^ | ^ | ^ |
143* | | | | | |
144* | | | | `T' <---- 2 bytes for Type
145* | | | |
146* | | '---SNAP--' <-------- 6 bytes for SNAP
147* | |
148* `-IV--' <-------------------- 4 bytes for IV (WEP)
149*
150* SNAP HEADER
151*
152*/
153
154static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
155static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
156
157static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
158{
159 struct ieee80211_snap_hdr *snap;
160 u8 *oui;
161
162 snap = (struct ieee80211_snap_hdr *)data;
163 snap->dsap = 0xaa;
164 snap->ssap = 0xaa;
165 snap->ctrl = 0x03;
166
167 if (h_proto == 0x8137 || h_proto == 0x80f3)
168 oui = P802_1H_OUI;
169 else
170 oui = RFC1042_OUI;
171 snap->oui[0] = oui[0];
172 snap->oui[1] = oui[1];
173 snap->oui[2] = oui[2];
174
175 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
176
177 return SNAP_SIZE + sizeof(u16);
178}
179
180int ieee80211_encrypt_fragment(
181 struct ieee80211_device *ieee,
182 struct sk_buff *frag,
183 int hdr_len)
184{
185 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
186 int res;
187
188 if (!(crypt && crypt->ops))
189 {
190 printk("=========>%s(), crypt is null\n", __FUNCTION__);
191 return -1;
192 }
193#ifdef CONFIG_IEEE80211_CRYPT_TKIP
194 struct ieee80211_hdr *header;
195
196 if (ieee->tkip_countermeasures &&
197 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
198 header = (struct ieee80211_hdr *) frag->data;
199 if (net_ratelimit()) {
200 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
201 "TX packet to %pM\n",
202 ieee->dev->name, header->addr1);
203 }
204 return -1;
205 }
206#endif
207 /* To encrypt, frame format is:
208 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
209
210 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
211 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
212 * call both MSDU and MPDU encryption functions from here. */
213 atomic_inc(&crypt->refcnt);
214 res = 0;
215 if (crypt->ops->encrypt_msdu)
216 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
217 if (res == 0 && crypt->ops->encrypt_mpdu)
218 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
219
220 atomic_dec(&crypt->refcnt);
221 if (res < 0) {
222 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
223 ieee->dev->name, frag->len);
224 ieee->ieee_stats.tx_discards++;
225 return -1;
226 }
227
228 return 0;
229}
230
231
232void ieee80211_txb_free(struct ieee80211_txb *txb) {
233 if (unlikely(!txb))
234 return;
235 kfree(txb);
236}
237
238struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
239 int gfp_mask)
240{
241 struct ieee80211_txb *txb;
242 int i;
243 txb = kmalloc(
244 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
245 gfp_mask);
246 if (!txb)
247 return NULL;
248
249 memset(txb, 0, sizeof(struct ieee80211_txb));
250 txb->nr_frags = nr_frags;
251 txb->frag_size = txb_size;
252
253 for (i = 0; i < nr_frags; i++) {
254 txb->fragments[i] = dev_alloc_skb(txb_size);
255 if (unlikely(!txb->fragments[i])) {
256 i--;
257 break;
258 }
259 memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
260 }
261 if (unlikely(i != nr_frags)) {
262 while (i >= 0)
263 dev_kfree_skb_any(txb->fragments[i--]);
264 kfree(txb);
265 return NULL;
266 }
267 return txb;
268}
269
270// Classify the to-be send data packet
271// Need to acquire the sent queue index.
272static int
273ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
274{
275 struct ethhdr *eth;
276 struct iphdr *ip;
277 eth = (struct ethhdr *)skb->data;
278 if (eth->h_proto != htons(ETH_P_IP))
279 return 0;
280
281 ip = ip_hdr(skb);
282 switch (ip->tos & 0xfc) {
283 case 0x20:
284 return 2;
285 case 0x40:
286 return 1;
287 case 0x60:
288 return 3;
289 case 0x80:
290 return 4;
291 case 0xa0:
292 return 5;
293 case 0xc0:
294 return 6;
295 case 0xe0:
296 return 7;
297 default:
298 return 0;
299 }
300}
301
302#define SN_LESS(a, b) (((a-b)&0x800)!=0)
303void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
304{
305 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
306 PTX_TS_RECORD pTxTs = NULL;
307 struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;
308
309 if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
310 return;
311 if (!IsQoSDataFrame(skb->data))
312 return;
313
314 if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
315 return;
316 //check packet and mode later
317#ifdef TO_DO_LIST
318 if(pTcb->PacketLength >= 4096)
319 return;
320 // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
321 if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
322 return;
323#endif
324
325 if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
326 {
327 return;
328 }
329
330
331#if 1
332 if (!ieee->GetNmodeSupportBySecCfg(ieee))
333 {
334 return;
335 }
336#endif
337 if(pHTInfo->bCurrentAMPDUEnable)
338 {
339 if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
340 {
341 printk("===>can't get TS\n");
342 return;
343 }
344 if (pTxTs->TxAdmittedBARecord.bValid == false)
345 {
346 //as some AP will refuse our action frame until key handshake has been finished. WB
347 if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA))
348 ;
349 else
350 TsStartAddBaProcess(ieee, pTxTs);
351 goto FORCED_AGG_SETTING;
352 }
353 else if (pTxTs->bUsingBa == false)
354 {
355 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
356 pTxTs->bUsingBa = true;
357 else
358 goto FORCED_AGG_SETTING;
359 }
360
361 if (ieee->iw_mode == IW_MODE_INFRA)
362 {
363 tcb_desc->bAMPDUEnable = true;
364 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
365 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
366 }
367 }
368FORCED_AGG_SETTING:
369 switch(pHTInfo->ForcedAMPDUMode )
370 {
371 case HT_AGG_AUTO:
372 break;
373
374 case HT_AGG_FORCE_ENABLE:
375 tcb_desc->bAMPDUEnable = true;
376 tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
377 tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
378 break;
379
380 case HT_AGG_FORCE_DISABLE:
381 tcb_desc->bAMPDUEnable = false;
382 tcb_desc->ampdu_density = 0;
383 tcb_desc->ampdu_factor = 0;
384 break;
385
386 }
387 return;
388}
389
390extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
391{
392 tcb_desc->bUseShortPreamble = false;
393 if (tcb_desc->data_rate == 2)
394 {//// 1M can only use Long Preamble. 11B spec
395 return;
396 }
397 else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
398 {
399 tcb_desc->bUseShortPreamble = true;
400 }
401 return;
402}
403extern void
404ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc)
405{
406 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
407
408 tcb_desc->bUseShortGI = false;
409
410 if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
411 return;
412
413 if(pHTInfo->bForcedShortGI)
414 {
415 tcb_desc->bUseShortGI = true;
416 return;
417 }
418
419 if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
420 tcb_desc->bUseShortGI = true;
421 else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
422 tcb_desc->bUseShortGI = true;
423}
424
425void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc)
426{
427 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
428
429 tcb_desc->bPacketBW = false;
430
431 if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
432 return;
433
434 if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
435 return;
436
437 if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel.
438 return;
439 //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
440 if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
441 tcb_desc->bPacketBW = true;
442 return;
443}
444
445void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
446{
447 // Common Settings
448 tcb_desc->bRTSSTBC = false;
449 tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
450 tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS
451 tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate.
452 tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz
453
454 if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts
455 return;
456
457 if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA.
458 return;
459
460 if (ieee->mode < IEEE_N_24G) //b, g mode
461 {
462 // (1) RTS_Threshold is compared to the MPDU, not MSDU.
463 // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame.
464 // Other fragments are protected by previous fragment.
465 // So we only need to check the length of first fragment.
466 if (skb->len > ieee->rts)
467 {
468 tcb_desc->bRTSEnable = true;
469 tcb_desc->rts_rate = MGN_24M;
470 }
471 else if (ieee->current_network.buseprotection)
472 {
473 // Use CTS-to-SELF in protection mode.
474 tcb_desc->bRTSEnable = true;
475 tcb_desc->bCTSEnable = true;
476 tcb_desc->rts_rate = MGN_24M;
477 }
478 //otherwise return;
479 return;
480 }
481 else
482 {// 11n High throughput case.
483 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
484 while (true)
485 {
486 //check ERP protection
487 if (ieee->current_network.buseprotection)
488 {// CTS-to-SELF
489 tcb_desc->bRTSEnable = true;
490 tcb_desc->bCTSEnable = true;
491 tcb_desc->rts_rate = MGN_24M;
492 break;
493 }
494 //check HT op mode
495 if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT)
496 {
497 u8 HTOpMode = pHTInfo->CurrentOpMode;
498 if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
499 (!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
500 {
501 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
502 tcb_desc->bRTSEnable = true;
503 break;
504 }
505 }
506 //check rts
507 if (skb->len > ieee->rts)
508 {
509 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
510 tcb_desc->bRTSEnable = true;
511 break;
512 }
513 //to do list: check MIMO power save condition.
514 //check AMPDU aggregation for TXOP
515 if(tcb_desc->bAMPDUEnable)
516 {
517 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
518 // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
519 // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
520 tcb_desc->bRTSEnable = false;
521 break;
522 }
523 //check IOT action
524 if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
525 {
526 tcb_desc->bCTSEnable = true;
527 tcb_desc->rts_rate = MGN_24M;
528 tcb_desc->bRTSEnable = true;
529 break;
530 }
531 // Totally no protection case!!
532 goto NO_PROTECTION;
533 }
534 }
535 // For test , CTS replace with RTS
536 if( 0 )
537 {
538 tcb_desc->bCTSEnable = true;
539 tcb_desc->rts_rate = MGN_24M;
540 tcb_desc->bRTSEnable = true;
541 }
542 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
543 tcb_desc->bUseShortPreamble = true;
544 if (ieee->mode == IW_MODE_MASTER)
545 goto NO_PROTECTION;
546 return;
547NO_PROTECTION:
548 tcb_desc->bRTSEnable = false;
549 tcb_desc->bCTSEnable = false;
550 tcb_desc->rts_rate = 0;
551 tcb_desc->RTSSC = 0;
552 tcb_desc->bRTSBW = false;
553}
554
555
556void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
557{
558#ifdef TO_DO_LIST
559 if(!IsDataFrame(pFrame))
560 {
561 pTcb->bTxDisableRateFallBack = TRUE;
562 pTcb->bTxUseDriverAssingedRate = TRUE;
563 pTcb->RATRIndex = 7;
564 return;
565 }
566
567 if(pMgntInfo->ForcedDataRate!= 0)
568 {
569 pTcb->bTxDisableRateFallBack = TRUE;
570 pTcb->bTxUseDriverAssingedRate = TRUE;
571 return;
572 }
573#endif
574 if(ieee->bTxDisableRateFallBack)
575 tcb_desc->bTxDisableRateFallBack = true;
576
577 if(ieee->bTxUseDriverAssingedRate)
578 tcb_desc->bTxUseDriverAssingedRate = true;
579 if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
580 {
581 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
582 tcb_desc->RATRIndex = 0;
583 }
584}
585
586void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
587{
588 if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
589 return;
590 if (IsQoSDataFrame(skb->data)) //we deal qos data only
591 {
592 PTX_TS_RECORD pTS = NULL;
593 if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
594 {
595 return;
596 }
597 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
598 }
599}
600
601int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
602{
603 struct ieee80211_device *ieee = netdev_priv(dev);
604 struct ieee80211_txb *txb = NULL;
605 struct ieee80211_hdr_3addrqos *frag_hdr;
606 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
607 unsigned long flags;
608 struct net_device_stats *stats = &ieee->stats;
609 int ether_type = 0, encrypt;
610 int bytes, fc, qos_ctl = 0, hdr_len;
611 struct sk_buff *skb_frag;
612 struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
613 .duration_id = 0,
614 .seq_ctl = 0,
615 .qos_ctl = 0
616 };
617 u8 dest[ETH_ALEN], src[ETH_ALEN];
618 int qos_actived = ieee->current_network.qos_data.active;
619
620 struct ieee80211_crypt_data* crypt;
621 bool bdhcp =false;
622
623 cb_desc *tcb_desc;
624
625 spin_lock_irqsave(&ieee->lock, flags);
626
627 /* If there is no driver handler to take the TXB, dont' bother
628 * creating it... */
629 if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
630 ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
631 printk(KERN_WARNING "%s: No xmit handler.\n",
632 ieee->dev->name);
633 goto success;
634 }
635
636
637 if(likely(ieee->raw_tx == 0)){
638 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
639 printk(KERN_WARNING "%s: skb too small (%d).\n",
640 ieee->dev->name, skb->len);
641 goto success;
642 }
643
644 memset(skb->cb, 0, sizeof(skb->cb));
645 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
646
647 crypt = ieee->crypt[ieee->tx_keyidx];
648
649 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
650 ieee->host_encrypt && crypt && crypt->ops;
651
652 if (!encrypt && ieee->ieee802_1x &&
653 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
654 stats->tx_dropped++;
655 goto success;
656 }
657 #ifdef CONFIG_IEEE80211_DEBUG
658 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
659 struct eapol *eap = (struct eapol *)(skb->data +
660 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
661 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
662 eap_get_type(eap->type));
663 }
664 #endif
665
666 // The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
667 // to prevent DHCP protocol fail
668 if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
669 if (ETH_P_IP == ether_type) {// IP header
670 const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
671 if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
672 struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
673 if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
674 ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
675 // 68 : UDP BOOTP client
676 // 67 : UDP BOOTP server
677 printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
678
679 bdhcp = true;
680#ifdef _RTL8192_EXT_PATCH_
681 ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
682#else
683 ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
684#endif
685 }
686 }
687 }else if(ETH_P_ARP == ether_type){// IP ARP packet
688 printk("=================>DHCP Protocol start tx ARP pkt!!\n");
689 bdhcp = true;
690 ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
691
692 }
693 }
694
695 /* Save source and destination addresses */
696 memcpy(&dest, skb->data, ETH_ALEN);
697 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
698
699 /* Advance the SKB to the start of the payload */
700 skb_pull(skb, sizeof(struct ethhdr));
701
702 /* Determine total amount of storage required for TXB packets */
703 bytes = skb->len + SNAP_SIZE + sizeof(u16);
704
705 if (encrypt)
706 fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
707 else
708
709 fc = IEEE80211_FTYPE_DATA;
710
711 if(qos_actived)
712 fc |= IEEE80211_STYPE_QOS_DATA;
713 else
714 fc |= IEEE80211_STYPE_DATA;
715
716 if (ieee->iw_mode == IW_MODE_INFRA) {
717 fc |= IEEE80211_FCTL_TODS;
718 /* To DS: Addr1 = BSSID, Addr2 = SA,
719 Addr3 = DA */
720 memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
721 memcpy(&header.addr2, &src, ETH_ALEN);
722 memcpy(&header.addr3, &dest, ETH_ALEN);
723 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
724 /* not From/To DS: Addr1 = DA, Addr2 = SA,
725 Addr3 = BSSID */
726 memcpy(&header.addr1, dest, ETH_ALEN);
727 memcpy(&header.addr2, src, ETH_ALEN);
728 memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
729 }
730
731 header.frame_ctl = cpu_to_le16(fc);
732
733 /* Determine fragmentation size based on destination (multicast
734 * and broadcast are not fragmented) */
735 if (is_multicast_ether_addr(header.addr1) ||
736 is_broadcast_ether_addr(header.addr1)) {
737 frag_size = MAX_FRAG_THRESHOLD;
738 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
739 }
740 else {
741 frag_size = ieee->fts;//default:392
742 qos_ctl = 0;
743 }
744
745 if(qos_actived)
746 {
747 hdr_len = IEEE80211_3ADDR_LEN + 2;
748
749 skb->priority = ieee80211_classify(skb, &ieee->current_network);
750 qos_ctl |= skb->priority; //set in the ieee80211_classify
751 header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
752 } else {
753 hdr_len = IEEE80211_3ADDR_LEN;
754 }
755 /* Determine amount of payload per fragment. Regardless of if
756 * this stack is providing the full 802.11 header, one will
757 * eventually be affixed to this fragment -- so we must account for
758 * it when determining the amount of payload space. */
759 bytes_per_frag = frag_size - hdr_len;
760 if (ieee->config &
761 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
762 bytes_per_frag -= IEEE80211_FCS_LEN;
763
764 /* Each fragment may need to have room for encryption pre/postfix */
765 if (encrypt)
766 bytes_per_frag -= crypt->ops->extra_prefix_len +
767 crypt->ops->extra_postfix_len;
768
769 /* Number of fragments is the total bytes_per_frag /
770 * payload_per_fragment */
771 nr_frags = bytes / bytes_per_frag;
772 bytes_last_frag = bytes % bytes_per_frag;
773 if (bytes_last_frag)
774 nr_frags++;
775 else
776 bytes_last_frag = bytes_per_frag;
777
778 /* When we allocate the TXB we allocate enough space for the reserve
779 * and full fragment bytes (bytes_per_frag doesn't include prefix,
780 * postfix, header, FCS, etc.) */
781 txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
782 if (unlikely(!txb)) {
783 printk(KERN_WARNING "%s: Could not allocate TXB\n",
784 ieee->dev->name);
785 goto failed;
786 }
787 txb->encrypted = encrypt;
788 txb->payload_size = bytes;
789
790 if(qos_actived)
791 {
792 txb->queue_index = UP2AC(skb->priority);
793 } else {
794 txb->queue_index = WME_AC_BK;
795 }
796
797
798
799 for (i = 0; i < nr_frags; i++) {
800 skb_frag = txb->fragments[i];
801 tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
802 if(qos_actived){
803 skb_frag->priority = skb->priority;//UP2AC(skb->priority);
804 tcb_desc->queue_index = UP2AC(skb->priority);
805 } else {
806 skb_frag->priority = WME_AC_BK;
807 tcb_desc->queue_index = WME_AC_BK;
808 }
809 skb_reserve(skb_frag, ieee->tx_headroom);
810
811 if (encrypt){
812 if (ieee->hwsec_active)
813 tcb_desc->bHwSec = 1;
814 else
815 tcb_desc->bHwSec = 0;
816 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
817 }
818 else
819 {
820 tcb_desc->bHwSec = 0;
821 }
822 frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
823 memcpy(frag_hdr, &header, hdr_len);
824
825 /* If this is not the last fragment, then add the MOREFRAGS
826 * bit to the frame control */
827 if (i != nr_frags - 1) {
828 frag_hdr->frame_ctl = cpu_to_le16(
829 fc | IEEE80211_FCTL_MOREFRAGS);
830 bytes = bytes_per_frag;
831
832 } else {
833 /* The last fragment takes the remaining length */
834 bytes = bytes_last_frag;
835 }
836
837 if(qos_actived)
838 {
839 // add 1 only indicate to corresponding seq number control 2006/7/12
840 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
841 } else {
842 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
843 }
844
845 /* Put a SNAP header on the first fragment */
846 if (i == 0) {
847 ieee80211_put_snap(
848 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
849 ether_type);
850 bytes -= SNAP_SIZE + sizeof(u16);
851 }
852
853 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
854
855 /* Advance the SKB... */
856 skb_pull(skb, bytes);
857
858 /* Encryption routine will move the header forward in order
859 * to insert the IV between the header and the payload */
860 if (encrypt)
861 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
862 if (ieee->config &
863 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
864 skb_put(skb_frag, 4);
865 }
866
867 if(qos_actived)
868 {
869 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
870 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
871 else
872 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
873 } else {
874 if (ieee->seq_ctrl[0] == 0xFFF)
875 ieee->seq_ctrl[0] = 0;
876 else
877 ieee->seq_ctrl[0]++;
878 }
879 }else{
880 if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
881 printk(KERN_WARNING "%s: skb too small (%d).\n",
882 ieee->dev->name, skb->len);
883 goto success;
884 }
885
886 txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
887 if(!txb){
888 printk(KERN_WARNING "%s: Could not allocate TXB\n",
889 ieee->dev->name);
890 goto failed;
891 }
892
893 txb->encrypted = 0;
894 txb->payload_size = skb->len;
895 memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
896 }
897
898 success:
899//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
900 if (txb)
901 {
902 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
903 tcb_desc->bTxEnableFwCalcDur = 1;
904 if (is_multicast_ether_addr(header.addr1))
905 tcb_desc->bMulticast = 1;
906 if (is_broadcast_ether_addr(header.addr1))
907 tcb_desc->bBroadcast = 1;
908 ieee80211_txrate_selectmode(ieee, tcb_desc);
909 if ( tcb_desc->bMulticast || tcb_desc->bBroadcast)
910 tcb_desc->data_rate = ieee->basic_rate;
911 else
912 tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
913
914 if(bdhcp == true){
915 tcb_desc->data_rate = MGN_1M;
916 tcb_desc->bTxDisableRateFallBack = 1;
917
918 tcb_desc->RATRIndex = 7;
919 tcb_desc->bTxUseDriverAssingedRate = 1;
920 tcb_desc->bdhcp = 1;
921 }
922
923
924 ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
925 ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
926 ieee80211_query_HTCapShortGI(ieee, tcb_desc);
927 ieee80211_query_BandwidthMode(ieee, tcb_desc);
928 ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
929 ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
930 }
931 spin_unlock_irqrestore(&ieee->lock, flags);
932 dev_kfree_skb_any(skb);
933 if (txb) {
934 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
935 ieee80211_softmac_xmit(txb, ieee);
936 }else{
937 if ((*ieee->hard_start_xmit)(txb, ieee) == 0) {
938 stats->tx_packets++;
939 stats->tx_bytes += txb->payload_size;
940 return 0;
941 }
942 ieee80211_txb_free(txb);
943 }
944 }
945
946 return 0;
947
948 failed:
949 spin_unlock_irqrestore(&ieee->lock, flags);
950 netif_stop_queue(dev);
951 stats->tx_errors++;
952 return 1;
953
954}
955
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
new file mode 100644
index 00000000000..6530d9b6829
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -0,0 +1,872 @@
1/******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31******************************************************************************/
32#include <linux/wireless.h>
33#include <linux/version.h>
34#include <linux/kmod.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37
38#include "ieee80211.h"
39
40struct modes_unit {
41 char *mode_string;
42 int mode_size;
43};
44struct modes_unit ieee80211_modes[] = {
45 {"a",1},
46 {"b",1},
47 {"g",1},
48 {"?",1},
49 {"N-24G",5},
50 {"N-5G",4},
51};
52
53#define iwe_stream_add_event_rsl iwe_stream_add_event
54
55#define MAX_CUSTOM_LEN 64
56static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
57 char *start, char *stop,
58 struct ieee80211_network *network,
59 struct iw_request_info *info)
60{
61 char custom[MAX_CUSTOM_LEN];
62 char proto_name[IFNAMSIZ];
63 char *pname = proto_name;
64 char *p;
65 struct iw_event iwe;
66 int i, j;
67 u16 max_rate, rate;
68 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
69
70 /* First entry *MUST* be the AP MAC address */
71 iwe.cmd = SIOCGIWAP;
72 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
73 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
74 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
75 /* Remaining entries will be displayed in the order we provide them */
76
77 /* Add the ESSID */
78 iwe.cmd = SIOCGIWESSID;
79 iwe.u.data.flags = 1;
80// if (network->flags & NETWORK_EMPTY_ESSID) {
81 if (network->ssid_len == 0) {
82 iwe.u.data.length = sizeof("<hidden>");
83 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
84 } else {
85 iwe.u.data.length = min(network->ssid_len, (u8)32);
86 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
87 }
88 /* Add the protocol name */
89 iwe.cmd = SIOCGIWNAME;
90 for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
91 if(network->mode&(1<<i)) {
92 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
93 pname +=ieee80211_modes[i].mode_size;
94 }
95 }
96 *pname = '\0';
97 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
98 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99 /* Add mode */
100 iwe.cmd = SIOCGIWMODE;
101 if (network->capability &
102 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
103 if (network->capability & WLAN_CAPABILITY_BSS)
104 iwe.u.mode = IW_MODE_MASTER;
105 else
106 iwe.u.mode = IW_MODE_ADHOC;
107 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
108 }
109
110 /* Add frequency/channel */
111 iwe.cmd = SIOCGIWFREQ;
112/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
113 iwe.u.freq.e = 3; */
114 iwe.u.freq.m = network->channel;
115 iwe.u.freq.e = 0;
116 iwe.u.freq.i = 0;
117 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
118 /* Add encryption capability */
119 iwe.cmd = SIOCGIWENCODE;
120 if (network->capability & WLAN_CAPABILITY_PRIVACY)
121 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
122 else
123 iwe.u.data.flags = IW_ENCODE_DISABLED;
124 iwe.u.data.length = 0;
125 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
126 /* Add basic and extended rates */
127 max_rate = 0;
128 p = custom;
129 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
130 for (i = 0, j = 0; i < network->rates_len; ) {
131 if (j < network->rates_ex_len &&
132 ((network->rates_ex[j] & 0x7F) <
133 (network->rates[i] & 0x7F)))
134 rate = network->rates_ex[j++] & 0x7F;
135 else
136 rate = network->rates[i++] & 0x7F;
137 if (rate > max_rate)
138 max_rate = rate;
139 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
140 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
141 }
142 for (; j < network->rates_ex_len; j++) {
143 rate = network->rates_ex[j] & 0x7F;
144 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
145 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
146 if (rate > max_rate)
147 max_rate = rate;
148 }
149
150 if (network->mode >= IEEE_N_24G)//add N rate here;
151 {
152 PHT_CAPABILITY_ELE ht_cap = NULL;
153 bool is40M = false, isShortGI = false;
154 u8 max_mcs = 0;
155 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
156 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
157 else
158 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
159 is40M = (ht_cap->ChlWidth)?1:0;
160 isShortGI = (ht_cap->ChlWidth)?
161 ((ht_cap->ShortGI40Mhz)?1:0):
162 ((ht_cap->ShortGI20Mhz)?1:0);
163
164 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
165 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
166 if (rate > max_rate)
167 max_rate = rate;
168 }
169 iwe.cmd = SIOCGIWRATE;
170 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
171 iwe.u.bitrate.value = max_rate * 500000;
172 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
173 IW_EV_PARAM_LEN);
174 iwe.cmd = IWEVCUSTOM;
175 iwe.u.data.length = p - custom;
176 if (iwe.u.data.length)
177 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
178 /* Add quality statistics */
179 /* TODO: Fix these values... */
180 iwe.cmd = IWEVQUAL;
181 iwe.u.qual.qual = network->stats.signal;
182 iwe.u.qual.level = network->stats.rssi;
183 iwe.u.qual.noise = network->stats.noise;
184 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
185 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
186 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
187 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
188 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
189 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
190 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
191 iwe.u.qual.updated = 7;
192 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
193 iwe.cmd = IWEVCUSTOM;
194 p = custom;
195
196 iwe.u.data.length = p - custom;
197 if (iwe.u.data.length)
198 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
199#if (WIRELESS_EXT < 18)
200 if (ieee->wpa_enabled && network->wpa_ie_len){
201 char buf[MAX_WPA_IE_LEN * 2 + 30];
202 u8 *p = buf;
203 p += sprintf(p, "wpa_ie=");
204 for (i = 0; i < network->wpa_ie_len; i++) {
205 p += sprintf(p, "%02x", network->wpa_ie[i]);
206 }
207
208 memset(&iwe, 0, sizeof(iwe));
209 iwe.cmd = IWEVCUSTOM;
210 iwe.u.data.length = strlen(buf);
211 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
212 }
213
214 if (ieee->wpa_enabled && network->rsn_ie_len){
215 char buf[MAX_WPA_IE_LEN * 2 + 30];
216
217 u8 *p = buf;
218 p += sprintf(p, "rsn_ie=");
219 for (i = 0; i < network->rsn_ie_len; i++) {
220 p += sprintf(p, "%02x", network->rsn_ie[i]);
221 }
222
223 memset(&iwe, 0, sizeof(iwe));
224 iwe.cmd = IWEVCUSTOM;
225 iwe.u.data.length = strlen(buf);
226 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
227 }
228#else
229 memset(&iwe, 0, sizeof(iwe));
230 if (network->wpa_ie_len)
231 {
232 char buf[MAX_WPA_IE_LEN];
233 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
234 iwe.cmd = IWEVGENIE;
235 iwe.u.data.length = network->wpa_ie_len;
236 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
237 }
238 memset(&iwe, 0, sizeof(iwe));
239 if (network->rsn_ie_len)
240 {
241 char buf[MAX_WPA_IE_LEN];
242 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
243 iwe.cmd = IWEVGENIE;
244 iwe.u.data.length = network->rsn_ie_len;
245 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
246 }
247#endif
248
249
250 /* Add EXTRA: Age to display seconds since last beacon/probe response
251 * for given network. */
252 iwe.cmd = IWEVCUSTOM;
253 p = custom;
254 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
255 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
256 iwe.u.data.length = p - custom;
257 if (iwe.u.data.length)
258 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
259
260 return start;
261}
262
263int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
264 struct iw_request_info *info,
265 union iwreq_data *wrqu, char *extra)
266{
267 struct ieee80211_network *network;
268 unsigned long flags;
269
270 char *ev = extra;
271// char *stop = ev + IW_SCAN_MAX_DATA;
272 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
273 //char *stop = ev + IW_SCAN_MAX_DATA;
274 int i = 0;
275 int err = 0;
276 IEEE80211_DEBUG_WX("Getting scan\n");
277 down(&ieee->wx_sem);
278 spin_lock_irqsave(&ieee->lock, flags);
279
280 list_for_each_entry(network, &ieee->network_list, list) {
281 i++;
282 if((stop-ev)<200)
283 {
284 err = -E2BIG;
285 break;
286 }
287 if (ieee->scan_age == 0 ||
288 time_after(network->last_scanned + ieee->scan_age, jiffies))
289 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
290 else
291 IEEE80211_DEBUG_SCAN(
292 "Not showing network '%s ("
293 "%pM)' due to age (%lums).\n",
294 escape_essid(network->ssid,
295 network->ssid_len),
296 network->bssid,
297 (jiffies - network->last_scanned) / (HZ / 100));
298 }
299
300 spin_unlock_irqrestore(&ieee->lock, flags);
301 up(&ieee->wx_sem);
302 wrqu->data.length = ev - extra;
303 wrqu->data.flags = 0;
304
305 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
306
307 return err;
308}
309
310int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
311 struct iw_request_info *info,
312 union iwreq_data *wrqu, char *keybuf)
313{
314 struct iw_point *erq = &(wrqu->encoding);
315 struct net_device *dev = ieee->dev;
316 struct ieee80211_security sec = {
317 .flags = 0
318 };
319 int i, key, key_provided, len;
320 struct ieee80211_crypt_data **crypt;
321
322 IEEE80211_DEBUG_WX("SET_ENCODE\n");
323
324 key = erq->flags & IW_ENCODE_INDEX;
325 if (key) {
326 if (key > WEP_KEYS)
327 return -EINVAL;
328 key--;
329 key_provided = 1;
330 } else {
331 key_provided = 0;
332 key = ieee->tx_keyidx;
333 }
334
335 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
336 "provided" : "default");
337 crypt = &ieee->crypt[key];
338
339 if (erq->flags & IW_ENCODE_DISABLED) {
340 if (key_provided && *crypt) {
341 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
342 key);
343 ieee80211_crypt_delayed_deinit(ieee, crypt);
344 } else
345 IEEE80211_DEBUG_WX("Disabling encryption.\n");
346
347 /* Check all the keys to see if any are still configured,
348 * and if no key index was provided, de-init them all */
349 for (i = 0; i < WEP_KEYS; i++) {
350 if (ieee->crypt[i] != NULL) {
351 if (key_provided)
352 break;
353 ieee80211_crypt_delayed_deinit(
354 ieee, &ieee->crypt[i]);
355 }
356 }
357
358 if (i == WEP_KEYS) {
359 sec.enabled = 0;
360 sec.level = SEC_LEVEL_0;
361 sec.flags |= SEC_ENABLED | SEC_LEVEL;
362 }
363
364 goto done;
365 }
366
367
368
369 sec.enabled = 1;
370 sec.flags |= SEC_ENABLED;
371
372 if (*crypt != NULL && (*crypt)->ops != NULL &&
373 strcmp((*crypt)->ops->name, "WEP") != 0) {
374 /* changing to use WEP; deinit previously used algorithm
375 * on this key */
376 ieee80211_crypt_delayed_deinit(ieee, crypt);
377 }
378
379 if (*crypt == NULL) {
380 struct ieee80211_crypt_data *new_crypt;
381
382 /* take WEP into use */
383 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
384 GFP_KERNEL);
385 if (new_crypt == NULL)
386 return -ENOMEM;
387 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
388 if (!new_crypt->ops)
389 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
390 if (new_crypt->ops)
391 new_crypt->priv = new_crypt->ops->init(key);
392
393 if (!new_crypt->ops || !new_crypt->priv) {
394 kfree(new_crypt);
395 new_crypt = NULL;
396
397 printk(KERN_WARNING "%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n",
399 dev->name);
400 return -EOPNOTSUPP;
401 }
402 *crypt = new_crypt;
403 }
404
405 /* If a new key was provided, set it up */
406 if (erq->length > 0) {
407 len = erq->length <= 5 ? 5 : 13;
408 memcpy(sec.keys[key], keybuf, erq->length);
409 if (len > erq->length)
410 memset(sec.keys[key] + erq->length, 0,
411 len - erq->length);
412 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
413 key, escape_essid(sec.keys[key], len),
414 erq->length, len);
415 sec.key_sizes[key] = len;
416 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
417 (*crypt)->priv);
418 sec.flags |= (1 << key);
419 /* This ensures a key will be activated if no key is
420 * explicitely set */
421 if (key == sec.active_key)
422 sec.flags |= SEC_ACTIVE_KEY;
423 ieee->tx_keyidx = key;
424
425 } else {
426 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
427 NULL, (*crypt)->priv);
428 if (len == 0) {
429 /* Set a default key of all 0 */
430 printk("Setting key %d to all zero.\n",
431 key);
432
433 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
434 key);
435 memset(sec.keys[key], 0, 13);
436 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
437 (*crypt)->priv);
438 sec.key_sizes[key] = 13;
439 sec.flags |= (1 << key);
440 }
441
442 /* No key data - just set the default TX key index */
443 if (key_provided) {
444 IEEE80211_DEBUG_WX(
445 "Setting key %d to default Tx key.\n", key);
446 ieee->tx_keyidx = key;
447 sec.active_key = key;
448 sec.flags |= SEC_ACTIVE_KEY;
449 }
450 }
451
452 done:
453 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
454 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
455 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
456 sec.flags |= SEC_AUTH_MODE;
457 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
458 "OPEN" : "SHARED KEY");
459
460 /* For now we just support WEP, so only set that security level...
461 * TODO: When WPA is added this is one place that needs to change */
462 sec.flags |= SEC_LEVEL;
463 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
464
465 if (ieee->set_security)
466 ieee->set_security(ieee, &sec);
467
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee->reset_on_keychange &&
474 ieee->iw_mode != IW_MODE_INFRA &&
475 ieee->reset_port && ieee->reset_port(ieee)) {
476 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
477 return -EINVAL;
478 }
479 return 0;
480}
481
482int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
483 struct iw_request_info *info,
484 union iwreq_data *wrqu, char *keybuf)
485{
486 struct iw_point *erq = &(wrqu->encoding);
487 int len, key;
488 struct ieee80211_crypt_data *crypt;
489
490 IEEE80211_DEBUG_WX("GET_ENCODE\n");
491
492 if(ieee->iw_mode == IW_MODE_MONITOR)
493 return -1;
494
495 key = erq->flags & IW_ENCODE_INDEX;
496 if (key) {
497 if (key > WEP_KEYS)
498 return -EINVAL;
499 key--;
500 } else
501 key = ieee->tx_keyidx;
502
503 crypt = ieee->crypt[key];
504 erq->flags = key + 1;
505
506 if (crypt == NULL || crypt->ops == NULL) {
507 erq->length = 0;
508 erq->flags |= IW_ENCODE_DISABLED;
509 return 0;
510 }
511#if 0
512 if (strcmp(crypt->ops->name, "WEP") != 0) {
513 /* only WEP is supported with wireless extensions, so just
514 * report that encryption is used */
515 erq->length = 0;
516 erq->flags |= IW_ENCODE_ENABLED;
517 return 0;
518 }
519#endif
520 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
521 erq->length = (len >= 0 ? len : 0);
522
523 erq->flags |= IW_ENCODE_ENABLED;
524
525 if (ieee->open_wep)
526 erq->flags |= IW_ENCODE_OPEN;
527 else
528 erq->flags |= IW_ENCODE_RESTRICTED;
529
530 return 0;
531}
532#if (WIRELESS_EXT >= 18)
533int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
534 struct iw_request_info *info,
535 union iwreq_data *wrqu, char *extra)
536{
537 int ret = 0;
538 struct net_device *dev = ieee->dev;
539 struct iw_point *encoding = &wrqu->encoding;
540 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
541 int i, idx;
542 int group_key = 0;
543 const char *alg;
544 struct ieee80211_crypto_ops *ops;
545 struct ieee80211_crypt_data **crypt;
546
547 struct ieee80211_security sec = {
548 .flags = 0,
549 };
550 idx = encoding->flags & IW_ENCODE_INDEX;
551 if (idx) {
552 if (idx < 1 || idx > WEP_KEYS)
553 return -EINVAL;
554 idx--;
555 } else
556 idx = ieee->tx_keyidx;
557
558 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
559
560 crypt = &ieee->crypt[idx];
561
562 group_key = 1;
563 } else {
564 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
565 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
566 return -EINVAL;
567 if (ieee->iw_mode == IW_MODE_INFRA)
568
569 crypt = &ieee->crypt[idx];
570
571 else
572 return -EINVAL;
573 }
574
575 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
576 if ((encoding->flags & IW_ENCODE_DISABLED) ||
577 ext->alg == IW_ENCODE_ALG_NONE) {
578 if (*crypt)
579 ieee80211_crypt_delayed_deinit(ieee, crypt);
580
581 for (i = 0; i < WEP_KEYS; i++)
582
583 if (ieee->crypt[i] != NULL)
584
585 break;
586
587 if (i == WEP_KEYS) {
588 sec.enabled = 0;
589 // sec.encrypt = 0;
590 sec.level = SEC_LEVEL_0;
591 sec.flags |= SEC_LEVEL;
592 }
593 goto done;
594 }
595
596 sec.enabled = 1;
597 // sec.encrypt = 1;
598#if 0
599 if (group_key ? !ieee->host_mc_decrypt :
600 !(ieee->host_encrypt || ieee->host_decrypt ||
601 ieee->host_encrypt_msdu))
602 goto skip_host_crypt;
603#endif
604 switch (ext->alg) {
605 case IW_ENCODE_ALG_WEP:
606 alg = "WEP";
607 break;
608 case IW_ENCODE_ALG_TKIP:
609 alg = "TKIP";
610 break;
611 case IW_ENCODE_ALG_CCMP:
612 alg = "CCMP";
613 break;
614 default:
615 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
616 dev->name, ext->alg);
617 ret = -EINVAL;
618 goto done;
619 }
620 printk("alg name:%s\n",alg);
621
622 ops = ieee80211_get_crypto_ops(alg);
623 if (ops == NULL)
624 ops = ieee80211_get_crypto_ops(alg);
625 if (ops == NULL) {
626 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
627 dev->name, ext->alg);
628 printk("========>unknown crypto alg %d\n", ext->alg);
629 ret = -EINVAL;
630 goto done;
631 }
632
633 if (*crypt == NULL || (*crypt)->ops != ops) {
634 struct ieee80211_crypt_data *new_crypt;
635
636 ieee80211_crypt_delayed_deinit(ieee, crypt);
637
638#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
639 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
640#else
641 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
642 memset(new_crypt,0,sizeof(*new_crypt));
643#endif
644 if (new_crypt == NULL) {
645 ret = -ENOMEM;
646 goto done;
647 }
648 new_crypt->ops = ops;
649 if (new_crypt->ops)
650 new_crypt->priv = new_crypt->ops->init(idx);
651 if (new_crypt->priv == NULL) {
652 kfree(new_crypt);
653 ret = -EINVAL;
654 goto done;
655 }
656 *crypt = new_crypt;
657
658 }
659
660 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
661 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
662 (*crypt)->priv) < 0) {
663 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
664 printk("key setting failed\n");
665 ret = -EINVAL;
666 goto done;
667 }
668#if 1
669 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
670 ieee->tx_keyidx = idx;
671 sec.active_key = idx;
672 sec.flags |= SEC_ACTIVE_KEY;
673 }
674
675 if (ext->alg != IW_ENCODE_ALG_NONE) {
676 //memcpy(sec.keys[idx], ext->key, ext->key_len);
677 sec.key_sizes[idx] = ext->key_len;
678 sec.flags |= (1 << idx);
679 if (ext->alg == IW_ENCODE_ALG_WEP) {
680 // sec.encode_alg[idx] = SEC_ALG_WEP;
681 sec.flags |= SEC_LEVEL;
682 sec.level = SEC_LEVEL_1;
683 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
684 // sec.encode_alg[idx] = SEC_ALG_TKIP;
685 sec.flags |= SEC_LEVEL;
686 sec.level = SEC_LEVEL_2;
687 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
688 // sec.encode_alg[idx] = SEC_ALG_CCMP;
689 sec.flags |= SEC_LEVEL;
690 sec.level = SEC_LEVEL_3;
691 }
692 /* Don't set sec level for group keys. */
693 if (group_key)
694 sec.flags &= ~SEC_LEVEL;
695 }
696#endif
697done:
698 if (ieee->set_security)
699 ieee->set_security(ieee, &sec);
700
701 if (ieee->reset_on_keychange &&
702 ieee->iw_mode != IW_MODE_INFRA &&
703 ieee->reset_port && ieee->reset_port(ieee)) {
704 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
705 return -EINVAL;
706 }
707 return ret;
708}
709
710int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
711 struct iw_request_info *info,
712 union iwreq_data *wrqu, char *extra)
713{
714 struct iw_point *encoding = &wrqu->encoding;
715 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
716 struct ieee80211_crypt_data *crypt;
717 int idx, max_key_len;
718
719 max_key_len = encoding->length - sizeof(*ext);
720 if (max_key_len < 0)
721 return -EINVAL;
722
723 idx = encoding->flags & IW_ENCODE_INDEX;
724 if (idx) {
725 if (idx < 1 || idx > WEP_KEYS)
726 return -EINVAL;
727 idx--;
728 } else
729 idx = ieee->tx_keyidx;
730
731 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
732 ext->alg != IW_ENCODE_ALG_WEP)
733 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
734 return -EINVAL;
735
736 crypt = ieee->crypt[idx];
737 encoding->flags = idx + 1;
738 memset(ext, 0, sizeof(*ext));
739
740 if (crypt == NULL || crypt->ops == NULL ) {
741 ext->alg = IW_ENCODE_ALG_NONE;
742 ext->key_len = 0;
743 encoding->flags |= IW_ENCODE_DISABLED;
744 } else {
745 if (strcmp(crypt->ops->name, "WEP") == 0 )
746 ext->alg = IW_ENCODE_ALG_WEP;
747 else if (strcmp(crypt->ops->name, "TKIP"))
748 ext->alg = IW_ENCODE_ALG_TKIP;
749 else if (strcmp(crypt->ops->name, "CCMP"))
750 ext->alg = IW_ENCODE_ALG_CCMP;
751 else
752 return -EINVAL;
753 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
754 encoding->flags |= IW_ENCODE_ENABLED;
755 if (ext->key_len &&
756 (ext->alg == IW_ENCODE_ALG_TKIP ||
757 ext->alg == IW_ENCODE_ALG_CCMP))
758 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
759
760 }
761
762 return 0;
763}
764
765int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
766 struct iw_request_info *info,
767 union iwreq_data *wrqu, char *extra)
768{
769 struct iw_mlme *mlme = (struct iw_mlme *) extra;
770 switch (mlme->cmd) {
771 case IW_MLME_DEAUTH:
772 case IW_MLME_DISASSOC:
773 ieee80211_disassociate(ieee);
774 break;
775 default:
776 return -EOPNOTSUPP;
777 }
778 return 0;
779}
780
781int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
782 struct iw_request_info *info,
783 struct iw_param *data, char *extra)
784{
785 switch (data->flags & IW_AUTH_INDEX) {
786 case IW_AUTH_WPA_VERSION:
787 /*need to support wpa2 here*/
788 break;
789 case IW_AUTH_CIPHER_PAIRWISE:
790 case IW_AUTH_CIPHER_GROUP:
791 case IW_AUTH_KEY_MGMT:
792 /*
793 * * Host AP driver does not use these parameters and allows
794 * * wpa_supplicant to control them internally.
795 * */
796 break;
797 case IW_AUTH_TKIP_COUNTERMEASURES:
798 ieee->tkip_countermeasures = data->value;
799 break;
800 case IW_AUTH_DROP_UNENCRYPTED:
801 ieee->drop_unencrypted = data->value;
802 break;
803
804 case IW_AUTH_80211_AUTH_ALG:
805 if(data->value & IW_AUTH_ALG_SHARED_KEY){
806 ieee->open_wep = 0;
807 ieee->auth_mode = 1;
808 }
809 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
810 ieee->open_wep = 1;
811 ieee->auth_mode = 0;
812 }
813 else if(data->value & IW_AUTH_ALG_LEAP){
814 ieee->open_wep = 1;
815 ieee->auth_mode = 2;
816 }
817 else
818 return -EINVAL;
819 break;
820
821#if 1
822 case IW_AUTH_WPA_ENABLED:
823 ieee->wpa_enabled = (data->value)?1:0;
824 break;
825
826#endif
827 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
828 ieee->ieee802_1x = data->value;
829 break;
830 case IW_AUTH_PRIVACY_INVOKED:
831 ieee->privacy_invoked = data->value;
832 break;
833 default:
834 return -EOPNOTSUPP;
835 }
836 return 0;
837}
838#endif
839#if 1
840int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
841{
842 u8 *buf;
843
844 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
845 {
846 return -EINVAL;
847 }
848
849
850 if (len)
851 {
852 if (len != ie[1]+2)
853 {
854 printk("len:%zu, ie:%d\n", len, ie[1]);
855 return -EINVAL;
856 }
857 buf = kmemdup(ie, len, GFP_KERNEL);
858 if (buf == NULL)
859 return -ENOMEM;
860 kfree(ieee->wpa_ie);
861 ieee->wpa_ie = buf;
862 ieee->wpa_ie_len = len;
863 }
864 else{
865 kfree(ieee->wpa_ie);
866 ieee->wpa_ie = NULL;
867 ieee->wpa_ie_len = 0;
868 }
869 return 0;
870
871}
872#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h
new file mode 100644
index 00000000000..8ddc8bf9dc2
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h
@@ -0,0 +1,69 @@
1#ifndef _BATYPE_H_
2#define _BATYPE_H_
3
4#define TOTAL_TXBA_NUM 16
5#define TOTAL_RXBA_NUM 16
6
7#define BA_SETUP_TIMEOUT 200
8#define BA_INACT_TIMEOUT 60000
9
10#define BA_POLICY_DELAYED 0
11#define BA_POLICY_IMMEDIATE 1
12
13#define ADDBA_STATUS_SUCCESS 0
14#define ADDBA_STATUS_REFUSED 37
15#define ADDBA_STATUS_INVALID_PARAM 38
16
17#define DELBA_REASON_QSTA_LEAVING 36
18#define DELBA_REASON_END_BA 37
19#define DELBA_REASON_UNKNOWN_BA 38
20#define DELBA_REASON_TIMEOUT 39
21/* whether need define BA Action frames here?
22struct ieee80211_ADDBA_Req{
23 struct ieee80211_header_data header;
24 u8 category;
25 u8
26} __attribute__ ((packed));
27*/
28//Is this need?I put here just to make it easier to define structure BA_RECORD //WB
29typedef union _SEQUENCE_CONTROL{
30 u16 ShortData;
31 struct
32 {
33 u16 FragNum:4;
34 u16 SeqNum:12;
35 }field;
36}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL;
37
38typedef union _BA_PARAM_SET {
39 u8 charData[2];
40 u16 shortData;
41 struct {
42 u16 AMSDU_Support:1;
43 u16 BAPolicy:1;
44 u16 TID:4;
45 u16 BufferSize:10;
46 } field;
47} BA_PARAM_SET, *PBA_PARAM_SET;
48
49typedef union _DELBA_PARAM_SET {
50 u8 charData[2];
51 u16 shortData;
52 struct {
53 u16 Reserved:11;
54 u16 Initiator:1;
55 u16 TID:4;
56 } field;
57} DELBA_PARAM_SET, *PDELBA_PARAM_SET;
58
59typedef struct _BA_RECORD {
60 struct timer_list Timer;
61 u8 bValid;
62 u8 DialogToken;
63 BA_PARAM_SET BaParamSet;
64 u16 BaTimeoutValue;
65 SEQUENCE_CONTROL BaStartSeqCtrl;
66} BA_RECORD, *PBA_RECORD;
67
68#endif //end _BATYPE_H_
69
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
new file mode 100644
index 00000000000..b690cbc5136
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
@@ -0,0 +1,676 @@
1/*
2 * This file is created to process BA Action Frame. According to 802.11 spec,
3 * there are 3 BA action types at all. And as BA is related to TS, this part
4 * need some struture defined in QOS side code. Also TX RX is going to be
5 * resturctured, so how to send ADDBAREQ ADDBARSP and DELBA packet is still
6 * on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
7 */
8#include "ieee80211.h"
9#include "rtl819x_BA.h"
10
11/*
12 * Activate BA entry. And if Time is nozero, start timer.
13 */
14void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
15{
16 pBA->bValid = true;
17 if(Time != 0)
18 mod_timer(&pBA->Timer, jiffies + MSECS(Time));
19}
20
21/*
22 * deactivate BA entry, including its timer.
23 */
24void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
25{
26 pBA->bValid = false;
27 del_timer_sync(&pBA->Timer);
28}
29
30/*
31 * deactivete BA entry in Tx Ts, and send DELBA.
32 */
33u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
34{
35 PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
36 PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
37 u8 bSendDELBA = false;
38
39 // Delete pending BA
40 if(pPendingBa->bValid)
41 {
42 DeActivateBAEntry(ieee, pPendingBa);
43 bSendDELBA = true;
44 }
45
46 // Delete admitted BA
47 if(pAdmittedBa->bValid)
48 {
49 DeActivateBAEntry(ieee, pAdmittedBa);
50 bSendDELBA = true;
51 }
52
53 return bSendDELBA;
54}
55
56/*
57 * deactivete BA entry in Tx Ts, and send DELBA.
58 */
59u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
60{
61 PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
62 u8 bSendDELBA = false;
63
64 if(pBa->bValid)
65 {
66 DeActivateBAEntry(ieee, pBa);
67 bSendDELBA = true;
68 }
69
70 return bSendDELBA;
71}
72
73/*
74 * reset BA entry
75 */
76void ResetBaEntry( PBA_RECORD pBA)
77{
78 pBA->bValid = false;
79 pBA->BaParamSet.shortData = 0;
80 pBA->BaTimeoutValue = 0;
81 pBA->DialogToken = 0;
82 pBA->BaStartSeqCtrl.ShortData = 0;
83}
84
85/*
86 * construct ADDBAREQ and ADDBARSP frame here together.
87 * return constructed skb to xmit
88 */
89static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
90{
91 struct sk_buff *skb = NULL;
92 struct ieee80211_hdr_3addr* BAReq = NULL;
93 u8* tag = NULL;
94 u16 tmp = 0;
95 u16 len = ieee->tx_headroom + 9;
96 //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
97 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
98 if (pBA == NULL||ieee == NULL)
99 {
100 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
101 return NULL;
102 }
103 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
104 if (skb == NULL)
105 {
106 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
107 return NULL;
108 }
109
110 memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
111 skb_reserve(skb, ieee->tx_headroom);
112
113 BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
114
115 memcpy(BAReq->addr1, Dst, ETH_ALEN);
116 memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
117
118 memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
119
120 BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
121
122 //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
123 tag = (u8*)skb_put(skb, 9);
124 *tag ++= ACT_CAT_BA;
125 *tag ++= type;
126 // Dialog Token
127 *tag ++= pBA->DialogToken;
128
129 if (ACT_ADDBARSP == type)
130 {
131 // Status Code
132 printk("=====>to send ADDBARSP\n");
133 tmp = cpu_to_le16(StatusCode);
134 memcpy(tag, (u8*)&tmp, 2);
135 tag += 2;
136 }
137 // BA Parameter Set
138 tmp = cpu_to_le16(pBA->BaParamSet.shortData);
139 memcpy(tag, (u8*)&tmp, 2);
140 tag += 2;
141 // BA Timeout Value
142 tmp = cpu_to_le16(pBA->BaTimeoutValue);
143 memcpy(tag, (u8*)&tmp, 2);
144 tag += 2;
145
146 if (ACT_ADDBAREQ == type)
147 {
148 // BA Start SeqCtrl
149 memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
150 tag += 2;
151 }
152
153 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
154 return skb;
155 //return NULL;
156}
157
158/*
159 * construct DELBA frame
160 */
161static struct sk_buff* ieee80211_DELBA(
162 struct ieee80211_device* ieee,
163 u8* dst,
164 PBA_RECORD pBA,
165 TR_SELECT TxRxSelect,
166 u16 ReasonCode
167 )
168{
169 DELBA_PARAM_SET DelbaParamSet;
170 struct sk_buff *skb = NULL;
171 struct ieee80211_hdr_3addr* Delba = NULL;
172 u8* tag = NULL;
173 u16 tmp = 0;
174 //len = head len + DELBA Parameter Set(2) + Reason Code(2)
175 u16 len = 6 + ieee->tx_headroom;
176
177 if (net_ratelimit())
178 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
179
180 memset(&DelbaParamSet, 0, 2);
181
182 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
183 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
184
185 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
186 if (skb == NULL)
187 {
188 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
189 return NULL;
190 }
191// memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
192 skb_reserve(skb, ieee->tx_headroom);
193
194 Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
195
196 memcpy(Delba->addr1, dst, ETH_ALEN);
197 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
198 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
199 Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
200
201 tag = (u8*)skb_put(skb, 6);
202
203 *tag ++= ACT_CAT_BA;
204 *tag ++= ACT_DELBA;
205
206 // DELBA Parameter Set
207 tmp = cpu_to_le16(DelbaParamSet.shortData);
208 memcpy(tag, (u8*)&tmp, 2);
209 tag += 2;
210 // Reason Code
211 tmp = cpu_to_le16(ReasonCode);
212 memcpy(tag, (u8*)&tmp, 2);
213 tag += 2;
214
215 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
216 if (net_ratelimit())
217 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
218 return skb;
219}
220
221/*
222 * send ADDBAReq frame out
223 * If any possible, please hide pBA in ieee.
224 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
225 */
226void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
227{
228 struct sk_buff *skb = NULL;
229 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
230
231 if (skb)
232 {
233 softmac_mgmt_xmit(skb, ieee);
234 //add statistic needed here.
235 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
236 //WB
237 }
238 else
239 {
240 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
241 }
242}
243
244/*
245 * send ADDBARSP frame out
246 * If any possible, please hide pBA in ieee.
247 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
248 */
249void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
250{
251 struct sk_buff *skb = NULL;
252 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
253 if (skb)
254 {
255 softmac_mgmt_xmit(skb, ieee);
256 //same above
257 }
258 else
259 {
260 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
261 }
262}
263
264/*
265 * send ADDBARSP frame out
266 * If any possible, please hide pBA in ieee.
267 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
268 */
269void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
270{
271 struct sk_buff *skb = NULL;
272 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
273 if (skb)
274 {
275 softmac_mgmt_xmit(skb, ieee);
276 //same above
277 }
278 else
279 {
280 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
281 }
282 return ;
283}
284
285int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
286{
287 struct ieee80211_hdr_3addr* req = NULL;
288 u16 rc = 0;
289 u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
290 PBA_RECORD pBA = NULL;
291 PBA_PARAM_SET pBaParamSet = NULL;
292 u16* pBaTimeoutVal = NULL;
293 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
294 PRX_TS_RECORD pTS = NULL;
295
296 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
297 {
298 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
299 return -1;
300 }
301
302 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
303
304 req = ( struct ieee80211_hdr_3addr*) skb->data;
305 tag = (u8*)req;
306 dst = (u8*)(&req->addr2[0]);
307 tag += sizeof( struct ieee80211_hdr_3addr);
308 pDialogToken = tag + 2; //category+action
309 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
310 pBaTimeoutVal = (u16*)(tag + 5);
311 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
312
313 printk("====================>rx ADDBAREQ from :%pM\n", dst);
314//some other capability is not ready now.
315 if( (ieee->current_network.qos_data.active == 0) ||
316 (ieee->pHTInfo->bCurrentHTSupport == false)) //||
317 // (ieee->pStaQos->bEnableRxImmBA == false) )
318 {
319 rc = ADDBA_STATUS_REFUSED;
320 IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
321 goto OnADDBAReq_Fail;
322 }
323 // Search for related traffic stream.
324 // If there is no matched TS, reject the ADDBA request.
325 if( !GetTs(
326 ieee,
327 (PTS_COMMON_INFO*)(&pTS),
328 dst,
329 (u8)(pBaParamSet->field.TID),
330 RX_DIR,
331 true) )
332 {
333 rc = ADDBA_STATUS_REFUSED;
334 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
335 goto OnADDBAReq_Fail;
336 }
337 pBA = &pTS->RxAdmittedBARecord;
338 // To Determine the ADDBA Req content
339 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
340 // I want to check StartSeqCtrl to make sure when we start aggregation!!!
341 //
342 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
343 {
344 rc = ADDBA_STATUS_INVALID_PARAM;
345 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
346 goto OnADDBAReq_Fail;
347 }
348 // Admit the ADDBA Request
349 //
350 DeActivateBAEntry(ieee, pBA);
351 pBA->DialogToken = *pDialogToken;
352 pBA->BaParamSet = *pBaParamSet;
353 pBA->BaTimeoutValue = *pBaTimeoutVal;
354 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
355 //for half N mode we only aggregate 1 frame
356 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
357 pBA->BaParamSet.field.BufferSize = 1;
358 else
359 pBA->BaParamSet.field.BufferSize = 32;
360 ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
361 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
362
363 // End of procedure.
364 return 0;
365
366OnADDBAReq_Fail:
367 {
368 BA_RECORD BA;
369 BA.BaParamSet = *pBaParamSet;
370 BA.BaTimeoutValue = *pBaTimeoutVal;
371 BA.DialogToken = *pDialogToken;
372 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
373 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
374 return 0; //we send RSP out.
375 }
376
377}
378
379int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
380{
381 struct ieee80211_hdr_3addr* rsp = NULL;
382 PBA_RECORD pPendingBA, pAdmittedBA;
383 PTX_TS_RECORD pTS = NULL;
384 u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
385 u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
386 PBA_PARAM_SET pBaParamSet = NULL;
387 u16 ReasonCode;
388
389 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
390 {
391 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
392 return -1;
393 }
394 rsp = ( struct ieee80211_hdr_3addr*)skb->data;
395 tag = (u8*)rsp;
396 dst = (u8*)(&rsp->addr2[0]);
397 tag += sizeof( struct ieee80211_hdr_3addr);
398 pDialogToken = tag + 2;
399 pStatusCode = (u16*)(tag + 3);
400 pBaParamSet = (PBA_PARAM_SET)(tag + 5);
401 pBaTimeoutVal = (u16*)(tag + 7);
402
403 // Check the capability
404 // Since we can always receive A-MPDU, we just check if it is under HT mode.
405 if( ieee->current_network.qos_data.active == 0 ||
406 ieee->pHTInfo->bCurrentHTSupport == false ||
407 ieee->pHTInfo->bCurrentAMPDUEnable == false )
408 {
409 IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
410 ReasonCode = DELBA_REASON_UNKNOWN_BA;
411 goto OnADDBARsp_Reject;
412 }
413
414
415 //
416 // Search for related TS.
417 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
418 //
419 if (!GetTs(
420 ieee,
421 (PTS_COMMON_INFO*)(&pTS),
422 dst,
423 (u8)(pBaParamSet->field.TID),
424 TX_DIR,
425 false) )
426 {
427 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
428 ReasonCode = DELBA_REASON_UNKNOWN_BA;
429 goto OnADDBARsp_Reject;
430 }
431
432 pTS->bAddBaReqInProgress = false;
433 pPendingBA = &pTS->TxPendingBARecord;
434 pAdmittedBA = &pTS->TxAdmittedBARecord;
435
436
437 //
438 // Check if related BA is waiting for setup.
439 // If not, reject by sending DELBA frame.
440 //
441 if((pAdmittedBA->bValid==true))
442 {
443 // Since BA is already setup, we ignore all other ADDBA Response.
444 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
445 return -1;
446 }
447 else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
448 {
449 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
450 ReasonCode = DELBA_REASON_UNKNOWN_BA;
451 goto OnADDBARsp_Reject;
452 }
453 else
454 {
455 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
456 DeActivateBAEntry(ieee, pPendingBA);
457 }
458
459
460 if(*pStatusCode == ADDBA_STATUS_SUCCESS)
461 {
462 //
463 // Determine ADDBA Rsp content here.
464 // We can compare the value of BA parameter set that Peer returned and Self sent.
465 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
466 //
467 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
468 {
469 // Since this is a kind of ADDBA failed, we delay next ADDBA process.
470 pTS->bAddBaReqDelayed = true;
471 DeActivateBAEntry(ieee, pAdmittedBA);
472 ReasonCode = DELBA_REASON_END_BA;
473 goto OnADDBARsp_Reject;
474 }
475
476
477 //
478 // Admitted condition
479 //
480 pAdmittedBA->DialogToken = *pDialogToken;
481 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
482 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
483 pAdmittedBA->BaParamSet = *pBaParamSet;
484 DeActivateBAEntry(ieee, pAdmittedBA);
485 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
486 }
487 else
488 {
489 // Delay next ADDBA process.
490 pTS->bAddBaReqDelayed = true;
491 }
492
493 // End of procedure
494 return 0;
495
496OnADDBARsp_Reject:
497 {
498 BA_RECORD BA;
499 BA.BaParamSet = *pBaParamSet;
500 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
501 return 0;
502 }
503
504}
505
506int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
507{
508 struct ieee80211_hdr_3addr* delba = NULL;
509 PDELBA_PARAM_SET pDelBaParamSet = NULL;
510 u16* pReasonCode = NULL;
511 u8* dst = NULL;
512
513 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
514 {
515 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
516 return -1;
517 }
518
519 if(ieee->current_network.qos_data.active == 0 ||
520 ieee->pHTInfo->bCurrentHTSupport == false )
521 {
522 IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
523 return -1;
524 }
525
526 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
527 delba = ( struct ieee80211_hdr_3addr*)skb->data;
528 dst = (u8*)(&delba->addr2[0]);
529 delba += sizeof( struct ieee80211_hdr_3addr);
530 pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
531 pReasonCode = (u16*)(delba+4);
532
533 if(pDelBaParamSet->field.Initiator == 1)
534 {
535 PRX_TS_RECORD pRxTs;
536
537 if( !GetTs(
538 ieee,
539 (PTS_COMMON_INFO*)&pRxTs,
540 dst,
541 (u8)pDelBaParamSet->field.TID,
542 RX_DIR,
543 false) )
544 {
545 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__);
546 return -1;
547 }
548
549 RxTsDeleteBA(ieee, pRxTs);
550 }
551 else
552 {
553 PTX_TS_RECORD pTxTs;
554
555 if(!GetTs(
556 ieee,
557 (PTS_COMMON_INFO*)&pTxTs,
558 dst,
559 (u8)pDelBaParamSet->field.TID,
560 TX_DIR,
561 false) )
562 {
563 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__);
564 return -1;
565 }
566
567 pTxTs->bUsingBa = false;
568 pTxTs->bAddBaReqInProgress = false;
569 pTxTs->bAddBaReqDelayed = false;
570 del_timer_sync(&pTxTs->TsAddBaTimer);
571 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
572 TxTsDeleteBA(ieee, pTxTs);
573 }
574 return 0;
575}
576
577/* ADDBA initiate. This can only be called by TX side. */
578void
579TsInitAddBA(
580 struct ieee80211_device* ieee,
581 PTX_TS_RECORD pTS,
582 u8 Policy,
583 u8 bOverwritePending
584 )
585{
586 PBA_RECORD pBA = &pTS->TxPendingBARecord;
587
588 if(pBA->bValid==true && bOverwritePending==false)
589 return;
590
591 // Set parameters to "Pending" variable set
592 DeActivateBAEntry(ieee, pBA);
593
594 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
595 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
596 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
597 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
598 // BufferSize: This need to be set according to A-MPDU vector
599 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
600 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
601 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
602
603 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
604
605 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
606}
607
608void
609TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
610{
611
612 if(TxRxSelect == TX_DIR)
613 {
614 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
615
616 if(TxTsDeleteBA(ieee, pTxTs))
617 ieee80211_send_DELBA(
618 ieee,
619 pTsCommonInfo->Addr,
620 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
621 TxRxSelect,
622 DELBA_REASON_END_BA);
623 }
624 else if(TxRxSelect == RX_DIR)
625 {
626 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
627 if(RxTsDeleteBA(ieee, pRxTs))
628 ieee80211_send_DELBA(
629 ieee,
630 pTsCommonInfo->Addr,
631 &pRxTs->RxAdmittedBARecord,
632 TxRxSelect,
633 DELBA_REASON_END_BA );
634 }
635}
636
637/*
638 * BA setup timer
639 * acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
640 */
641void BaSetupTimeOut(unsigned long data)
642{
643 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
644
645 pTxTs->bAddBaReqInProgress = false;
646 pTxTs->bAddBaReqDelayed = true;
647 pTxTs->TxPendingBARecord.bValid = false;
648}
649
650void TxBaInactTimeout(unsigned long data)
651{
652 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
653 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
654 TxTsDeleteBA(ieee, pTxTs);
655 ieee80211_send_DELBA(
656 ieee,
657 pTxTs->TsCommonInfo.Addr,
658 &pTxTs->TxAdmittedBARecord,
659 TX_DIR,
660 DELBA_REASON_TIMEOUT);
661}
662
663void RxBaInactTimeout(unsigned long data)
664{
665 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
666 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
667
668 RxTsDeleteBA(ieee, pRxTs);
669 ieee80211_send_DELBA(
670 ieee,
671 pRxTs->TsCommonInfo.Addr,
672 &pRxTs->RxAdmittedBARecord,
673 RX_DIR,
674 DELBA_REASON_TIMEOUT);
675}
676
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
new file mode 100644
index 00000000000..56a120cf629
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
@@ -0,0 +1,483 @@
1#ifndef _RTL819XU_HTTYPE_H_
2#define _RTL819XU_HTTYPE_H_
3
4//------------------------------------------------------------
5// The HT Capability element is present in beacons, association request,
6// reassociation request and probe response frames
7//------------------------------------------------------------
8
9//
10// Operation mode value
11//
12#define HT_OPMODE_NO_PROTECT 0
13#define HT_OPMODE_OPTIONAL 1
14#define HT_OPMODE_40MHZ_PROTECT 2
15#define HT_OPMODE_MIXED 3
16
17//
18// MIMO Power Save Setings
19//
20#define MIMO_PS_STATIC 0
21#define MIMO_PS_DYNAMIC 1
22#define MIMO_PS_NOLIMIT 3
23
24
25//
26// There should be 128 bits to cover all of the MCS rates. However, since
27// 8190 does not support too much rates, one integer is quite enough.
28//
29
30#define sHTCLng 4
31
32
33#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff
34#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00
35#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
36
37
38typedef enum _HT_MCS_RATE{
39 HT_MCS0 = 0x00000001,
40 HT_MCS1 = 0x00000002,
41 HT_MCS2 = 0x00000004,
42 HT_MCS3 = 0x00000008,
43 HT_MCS4 = 0x00000010,
44 HT_MCS5 = 0x00000020,
45 HT_MCS6 = 0x00000040,
46 HT_MCS7 = 0x00000080,
47 HT_MCS8 = 0x00000100,
48 HT_MCS9 = 0x00000200,
49 HT_MCS10 = 0x00000400,
50 HT_MCS11 = 0x00000800,
51 HT_MCS12 = 0x00001000,
52 HT_MCS13 = 0x00002000,
53 HT_MCS14 = 0x00004000,
54 HT_MCS15 = 0x00008000,
55 // Do not define MCS32 here although 8190 support MCS32
56}HT_MCS_RATE,*PHT_MCS_RATE;
57
58//
59// Represent Channel Width in HT Capabilities
60//
61typedef enum _HT_CHANNEL_WIDTH{
62 HT_CHANNEL_WIDTH_20 = 0,
63 HT_CHANNEL_WIDTH_20_40 = 1,
64}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
65
66//
67// Represent Extension Channel Offset in HT Capabilities
68// This is available only in 40Mhz mode.
69//
70typedef enum _HT_EXTCHNL_OFFSET{
71 HT_EXTCHNL_OFFSET_NO_EXT = 0,
72 HT_EXTCHNL_OFFSET_UPPER = 1,
73 HT_EXTCHNL_OFFSET_NO_DEF = 2,
74 HT_EXTCHNL_OFFSET_LOWER = 3,
75}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
76
77typedef enum _CHNLOP{
78 CHNLOP_NONE = 0, // No Action now
79 CHNLOP_SCAN = 1, // Scan in progress
80 CHNLOP_SWBW = 2, // Bandwidth switching in progress
81 CHNLOP_SWCHNL = 3, // Software Channel switching in progress
82} CHNLOP, *PCHNLOP;
83
84// Determine if the Channel Operation is in progress
85#define CHHLOP_IN_PROGRESS(_pHTInfo) \
86 ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE
87
88/*
89typedef union _HT_CAPABILITY{
90 u16 ShortData;
91 u8 CharData[2];
92 struct
93 {
94 u16 AdvCoding:1;
95 u16 ChlWidth:1;
96 u16 MimoPwrSave:2;
97 u16 GreenField:1;
98 u16 ShortGI20Mhz:1;
99 u16 ShortGI40Mhz:1;
100 u16 STBC:1;
101 u16 BeamForm:1;
102 u16 DelayBA:1;
103 u16 MaxAMSDUSize:1;
104 u16 DssCCk:1;
105 u16 PSMP:1;
106 u16 Rsvd:3;
107 }Field;
108}HT_CAPABILITY, *PHT_CAPABILITY;
109
110typedef union _HT_CAPABILITY_MACPARA{
111 u8 ShortData;
112 u8 CharData[1];
113 struct
114 {
115 u8 MaxRxAMPDU:2;
116 u8 MPDUDensity:2;
117 u8 Rsvd:4;
118 }Field;
119}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA;
120*/
121
122typedef enum _HT_ACTION{
123 ACT_RECOMMAND_WIDTH = 0,
124 ACT_MIMO_PWR_SAVE = 1,
125 ACT_PSMP = 2,
126 ACT_SET_PCO_PHASE = 3,
127 ACT_MIMO_CHL_MEASURE = 4,
128 ACT_RECIPROCITY_CORRECT = 5,
129 ACT_MIMO_CSI_MATRICS = 6,
130 ACT_MIMO_NOCOMPR_STEER = 7,
131 ACT_MIMO_COMPR_STEER = 8,
132 ACT_ANTENNA_SELECT = 9,
133} HT_ACTION, *PHT_ACTION;
134
135
136/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */
137typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
138 SC_MODE_DUPLICATE = 0,
139 SC_MODE_LOWER = 1,
140 SC_MODE_UPPER = 2,
141 SC_MODE_FULL40MHZ = 3,
142}HT_BW40_SC_E;
143
144typedef struct _HT_CAPABILITY_ELE{
145
146 //HT capability info
147 u8 AdvCoding:1;
148 u8 ChlWidth:1;
149 u8 MimoPwrSave:2;
150 u8 GreenField:1;
151 u8 ShortGI20Mhz:1;
152 u8 ShortGI40Mhz:1;
153 u8 TxSTBC:1;
154 u8 RxSTBC:2;
155 u8 DelayBA:1;
156 u8 MaxAMSDUSize:1;
157 u8 DssCCk:1;
158 u8 PSMP:1;
159 u8 Rsvd1:1;
160 u8 LSigTxopProtect:1;
161
162 //MAC HT parameters info
163 u8 MaxRxAMPDUFactor:2;
164 u8 MPDUDensity:3;
165 u8 Rsvd2:3;
166
167 //Supported MCS set
168 u8 MCS[16];
169
170
171 //Extended HT Capability Info
172 u16 ExtHTCapInfo;
173
174 //TXBF Capabilities
175 u8 TxBFCap[4];
176
177 //Antenna Selection Capabilities
178 u8 ASCap;
179
180} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
181
182//------------------------------------------------------------
183// The HT Information element is present in beacons
184// Only AP is required to include this element
185//------------------------------------------------------------
186
187typedef struct _HT_INFORMATION_ELE{
188 u8 ControlChl;
189
190 u8 ExtChlOffset:2;
191 u8 RecommemdedTxWidth:1;
192 u8 RIFS:1;
193 u8 PSMPAccessOnly:1;
194 u8 SrvIntGranularity:3;
195
196 u8 OptMode:2;
197 u8 NonGFDevPresent:1;
198 u8 Revd1:5;
199 u8 Revd2:8;
200
201 u8 Rsvd3:6;
202 u8 DualBeacon:1;
203 u8 DualCTSProtect:1;
204
205 u8 SecondaryBeacon:1;
206 u8 LSigTxopProtectFull:1;
207 u8 PcoActive:1;
208 u8 PcoPhase:1;
209 u8 Rsvd4:4;
210
211 u8 BasicMSC[16];
212} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
213
214//
215// MIMO Power Save control field.
216// This is appear in MIMO Power Save Action Frame
217//
218typedef struct _MIMOPS_CTRL{
219 u8 MimoPsEnable:1;
220 u8 MimoPsMode:1;
221 u8 Reserved:6;
222} MIMOPS_CTRL, *PMIMOPS_CTRL;
223
224typedef enum _HT_SPEC_VER{
225 HT_SPEC_VER_IEEE = 0,
226 HT_SPEC_VER_EWC = 1,
227}HT_SPEC_VER, *PHT_SPEC_VER;
228
229typedef enum _HT_AGGRE_MODE_E{
230 HT_AGG_AUTO = 0,
231 HT_AGG_FORCE_ENABLE = 1,
232 HT_AGG_FORCE_DISABLE = 2,
233}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
234
235//------------------------------------------------------------
236// The Data structure is used to keep HT related variables when card is
237// configured as non-AP STA mode. **Note** Current_xxx should be set
238// to default value in HTInitializeHTInfo()
239//------------------------------------------------------------
240
241typedef struct _RT_HIGH_THROUGHPUT{
242 u8 bEnableHT;
243 u8 bCurrentHTSupport;
244
245 u8 bRegBW40MHz; // Tx 40MHz channel capablity
246 u8 bCurBW40MHz; // Tx 40MHz channel capability
247
248 u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
249 u8 bCurShortGI40MHz; // Tx Short GI for 40MHz
250
251 u8 bRegShortGI20MHz; // Tx Short GI for 20MHz
252 u8 bCurShortGI20MHz; // Tx Short GI for 20MHz
253
254 u8 bRegSuppCCK; // Tx CCK rate capability
255 u8 bCurSuppCCK; // Tx CCK rate capability
256
257 // 802.11n spec version for "peer"
258 HT_SPEC_VER ePeerHTSpecVer;
259
260
261 // HT related information for "Self"
262 HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
263 HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
264
265 // HT related information for "Peer"
266 u8 PeerHTCapBuf[32];
267 u8 PeerHTInfoBuf[32];
268
269
270 // A-MSDU related
271 u8 bAMSDU_Support; // This indicates Tx A-MSDU capability
272 u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability
273 u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability
274 u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability
275
276
277 // AMPDU related <2006.08.10 Emily>
278 u8 bAMPDUEnable; // This indicate Tx A-MPDU capability
279 u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability
280 u8 AMPDU_Factor; // This indicate Tx A-MPDU capability
281 u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability
282 u8 MPDU_Density; // This indicate Tx A-MPDU capability
283 u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability
284
285 // Forced A-MPDU enable
286 HT_AGGRE_MODE_E ForcedAMPDUMode;
287 u8 ForcedAMPDUFactor;
288 u8 ForcedMPDUDensity;
289
290 // Forced A-MSDU enable
291 HT_AGGRE_MODE_E ForcedAMSDUMode;
292 u16 ForcedAMSDUMaxSize;
293
294 u8 bForcedShortGI;
295
296 u8 CurrentOpMode;
297
298 // MIMO PS related
299 u8 SelfMimoPs;
300 u8 PeerMimoPs;
301
302 // 40MHz Channel Offset settings.
303 HT_EXTCHNL_OFFSET CurSTAExtChnlOffset;
304 u8 bCurTxBW40MHz; // If we use 40 MHz to Tx
305 u8 PeerBandwidth;
306
307 // For Bandwidth Switching
308 u8 bSwBwInProgress;
309 CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15.
310 u8 SwBwStep;
311 //struct timer_list SwBwTimer; //moved to ieee80211_device. as timer_list need include some header file here.
312
313 // For Realtek proprietary A-MPDU factor for aggregation
314 u8 bRegRT2RTAggregation;
315 u8 bCurrentRT2RTAggregation;
316 u8 bCurrentRT2RTLongSlotTime;
317 u8 szRT2RTAggBuffer[10];
318
319 // Rx Reorder control
320 u8 bRegRxReorderEnable;
321 u8 bCurRxReorderEnable;
322 u8 RxReorderWinSize;
323 u8 RxReorderPendingTime;
324 u16 RxReorderDropCounter;
325
326#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
327 u8 UsbTxAggrNum;
328#endif
329#ifdef USB_RX_AGGREGATION_SUPPORT
330 u8 UsbRxFwAggrEn;
331 u8 UsbRxFwAggrPageNum;
332 u8 UsbRxFwAggrPacketNum;
333 u8 UsbRxFwAggrTimeout;
334#endif
335
336 // Add for Broadcom(Linksys) IOT. Joseph
337 u8 bIsPeerBcm;
338
339 // For IOT issue.
340 u8 IOTPeer;
341 u32 IOTAction;
342} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
343
344
345//------------------------------------------------------------
346// The Data structure is used to keep HT related variable for "each Sta"
347// when card is configured as "AP mode"
348//------------------------------------------------------------
349
350typedef struct _RT_HTINFO_STA_ENTRY{
351 u8 bEnableHT;
352
353 u8 bSupportCck;
354
355 u16 AMSDU_MaxSize;
356
357 u8 AMPDU_Factor;
358 u8 MPDU_Density;
359
360 u8 HTHighestOperaRate;
361
362 u8 bBw40MHz;
363
364 u8 MimoPs;
365
366 u8 McsRateSet[16];
367
368
369}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
370
371
372
373
374
375//------------------------------------------------------------
376// The Data structure is used to keep HT related variable for "each AP"
377// when card is configured as "STA mode"
378//------------------------------------------------------------
379
380typedef struct _BSS_HT{
381
382 u8 bdSupportHT;
383
384 // HT related elements
385 u8 bdHTCapBuf[32];
386 u16 bdHTCapLen;
387 u8 bdHTInfoBuf[32];
388 u16 bdHTInfoLen;
389
390 HT_SPEC_VER bdHTSpecVer;
391 //HT_CAPABILITY_ELE bdHTCapEle;
392 //HT_INFORMATION_ELE bdHTInfoEle;
393
394 u8 bdRT2RTAggregation;
395 u8 bdRT2RTLongSlotTime;
396} __attribute__ ((packed)) BSS_HT, *PBSS_HT;
397
398typedef struct _MIMO_RSSI{
399 u32 EnableAntenna;
400 u32 AntennaA;
401 u32 AntennaB;
402 u32 AntennaC;
403 u32 AntennaD;
404 u32 Average;
405}MIMO_RSSI, *PMIMO_RSSI;
406
407typedef struct _MIMO_EVM{
408 u32 EVM1;
409 u32 EVM2;
410}MIMO_EVM, *PMIMO_EVM;
411
412typedef struct _FALSE_ALARM_STATISTICS{
413 u32 Cnt_Parity_Fail;
414 u32 Cnt_Rate_Illegal;
415 u32 Cnt_Crc8_fail;
416 u32 Cnt_all;
417}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
418
419
420extern u8 MCS_FILTER_ALL[16];
421extern u8 MCS_FILTER_1SS[16];
422
423/* 2007/07/11 MH Modify the macro. Becaus STA may link with a N-AP. If we set
424 STA in A/B/G mode and AP is still in N mode. The macro will be wrong. We have
425 to add a macro to judge wireless mode. */
426#define PICK_RATE(_nLegacyRate, _nMcsRate) \
427 (_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate)
428/* 2007/07/12 MH We only define legacy and HT wireless mode now. */
429#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK
430
431#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \
432 ((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\
433 (LegacyRate):\
434 (PICK_RATE(LegacyRate, HTRate))
435
436
437
438// MCS Bw 40 {1~7, 12~15,32}
439#define RATE_ADPT_1SS_MASK 0xFF
440#define RATE_ADPT_2SS_MASK 0xF0 //Skip MCS8~11 because mcs7 > mcs6, 9, 10, 11. 2007.01.16 by Emily
441#define RATE_ADPT_MCS32_MASK 0x01
442
443#define IS_11N_MCS_RATE(rate) (rate&0x80)
444
445typedef enum _HT_AGGRE_SIZE{
446 HT_AGG_SIZE_8K = 0,
447 HT_AGG_SIZE_16K = 1,
448 HT_AGG_SIZE_32K = 2,
449 HT_AGG_SIZE_64K = 3,
450}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E;
451
452/* Indicate different AP vendor for IOT issue */
453typedef enum _HT_IOT_PEER
454{
455 HT_IOT_PEER_UNKNOWN = 0,
456 HT_IOT_PEER_REALTEK = 1,
457 HT_IOT_PEER_BROADCOM = 2,
458 HT_IOT_PEER_RALINK = 3,
459 HT_IOT_PEER_ATHEROS = 4,
460 HT_IOT_PEER_CISCO= 5,
461 HT_IOT_PEER_MARVELL=6,
462 HT_IOT_PEER_MAX = 7
463}HT_IOT_PEER_E, *PHTIOT_PEER_E;
464
465//
466// IOT Action for different AP
467//
468typedef enum _HT_IOT_ACTION{
469 HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
470 HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
471 HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
472 HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
473 HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
474 HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
475 HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
476 HT_IOT_ACT_CDD_FSYNC = 0x00000080,
477 HT_IOT_ACT_PURE_N_MODE = 0x00000100,
478 HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
479 HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
480}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
481
482#endif //_RTL819XU_HTTYPE_H_
483
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
new file mode 100644
index 00000000000..f7a9da3ec82
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -0,0 +1,1732 @@
1
2//As this function is mainly ported from Windows driver, so leave the name little changed. If any confusion caused, tell me. Created by WB. 2008.05.08
3#include "ieee80211.h"
4#include "rtl819x_HT.h"
5u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
6
7u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
8
9u16 MCS_DATA_RATE[2][2][77] =
10 { { {13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78 ,104, 156, 208, 234, 260,
11 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520,
12 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195,
13 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260,
14 286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429}, // Long GI, 20MHz
15 {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289,
16 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578,
17 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217,
18 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289,
19 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477} }, // Short GI, 20MHz
20 { {27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540,
21 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080,
22 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405,
23 405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540,
24 594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891}, // Long GI, 40MHz
25 {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600,
26 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200,
27 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450,
28 450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600,
29 660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990} } // Short GI, 40MHz
30 };
31
32static const u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
33static const u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
34static const u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
35//static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
36static const u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};
37static const u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
38static const u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
39static const u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
40static const u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
41static const u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
42static const u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
43static const u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
44
45// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
46// code in other place??
47//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
48/********************************************************************************************************************
49 *function: This function update default settings in pHTInfo structure
50 * input: PRT_HIGH_THROUGHPUT pHTInfo
51 * output: none
52 * return: none
53 * notice: These value need be modified if any changes.
54 * *****************************************************************************************************************/
55void HTUpdateDefaultSetting(struct ieee80211_device* ieee)
56{
57 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
58
59 // ShortGI support
60 pHTInfo->bRegShortGI20MHz= 1;
61 pHTInfo->bRegShortGI40MHz= 1;
62
63 // 40MHz channel support
64 pHTInfo->bRegBW40MHz = 1;
65
66 // CCK rate support in 40MHz channel
67 if(pHTInfo->bRegBW40MHz)
68 pHTInfo->bRegSuppCCK = 1;
69 else
70 pHTInfo->bRegSuppCCK = true;
71
72 // AMSDU related
73 pHTInfo->nAMSDU_MaxSize = 7935UL;
74 pHTInfo->bAMSDU_Support = 0;
75
76 // AMPDU related
77 pHTInfo->bAMPDUEnable = 1;
78 pHTInfo->AMPDU_Factor = 2; //// 0: 2n13(8K), 1:2n14(16K), 2:2n15(32K), 3:2n16(64k)
79 pHTInfo->MPDU_Density = 0;// 0: No restriction, 1: 1/8usec, 2: 1/4usec, 3: 1/2usec, 4: 1usec, 5: 2usec, 6: 4usec, 7:8usec
80
81 // MIMO Power Save
82 pHTInfo->SelfMimoPs = 3;// 0: Static Mimo Ps, 1: Dynamic Mimo Ps, 3: No Limitation, 2: Reserved(Set to 3 automatically.)
83 if(pHTInfo->SelfMimoPs == 2)
84 pHTInfo->SelfMimoPs = 3;
85 // 8190 only. Assign rate operation mode to firmware
86 ieee->bTxDisableRateFallBack = 0;
87 ieee->bTxUseDriverAssingedRate = 0;
88
89#ifdef TO_DO_LIST
90 // 8190 only. Assign duration operation mode to firmware
91 pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur;
92#endif
93 // 8190 only, Realtek proprietary aggregation mode
94 // Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others
95 pHTInfo->bRegRT2RTAggregation = 1;//0: Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others
96
97 // For Rx Reorder Control
98 pHTInfo->bRegRxReorderEnable = 1;
99 pHTInfo->RxReorderWinSize = 64;
100 pHTInfo->RxReorderPendingTime = 30;
101
102#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
103 pHTInfo->UsbTxAggrNum = 4;
104#endif
105#ifdef USB_RX_AGGREGATION_SUPPORT
106 pHTInfo->UsbRxFwAggrEn = 1;
107 pHTInfo->UsbRxFwAggrPageNum = 24;
108 pHTInfo->UsbRxFwAggrPacketNum = 8;
109 pHTInfo->UsbRxFwAggrTimeout = 16; ////usb rx FW aggregation timeout threshold.It's in units of 64us
110#endif
111
112
113}
114/********************************************************************************************************************
115 *function: This function print out each field on HT capability IE mainly from (Beacon/ProbeRsp/AssocReq)
116 * input: u8* CapIE //Capability IE to be printed out
117 * u8* TitleString //mainly print out caller function
118 * output: none
119 * return: none
120 * notice: Driver should not print out this message by default.
121 * *****************************************************************************************************************/
122void HTDebugHTCapability(u8* CapIE, u8* TitleString )
123{
124
125 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
126 PHT_CAPABILITY_ELE pCapELE;
127
128 if(!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap)))
129 {
130 //EWC IE
131 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
132 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]);
133 }else
134 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]);
135
136 IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Capability>. Called by %s\n", TitleString );
137
138 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth)?"20MHz": "20/40MHz");
139 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz)?"YES": "NO");
140 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz)?"YES": "NO");
141 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC)?"YES": "NO");
142 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize)?"3839": "7935");
143 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk)?"YES": "NO");
144 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor);
145 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMPDU Density = %d\n", pCapELE->MPDUDensity);
146 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\
147 pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]);
148}
149/********************************************************************************************************************
150 *function: This function print out each field on HT Information IE mainly from (Beacon/ProbeRsp)
151 * input: u8* InfoIE //Capability IE to be printed out
152 * u8* TitleString //mainly print out caller function
153 * output: none
154 * return: none
155 * notice: Driver should not print out this message by default.
156 * *****************************************************************************************************************/
157void HTDebugHTInfo(u8* InfoIE, u8* TitleString)
158{
159
160 static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily
161 PHT_INFORMATION_ELE pHTInfoEle;
162
163 if(!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
164 {
165 // Not EWC IE
166 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
167 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]);
168 }else
169 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]);
170
171
172 IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Information Element>. Called by %s\n", TitleString);
173
174 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl);
175 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSenondary channel =");
176 switch(pHTInfoEle->ExtChlOffset)
177 {
178 case 0:
179 IEEE80211_DEBUG(IEEE80211_DL_HT, "Not Present\n");
180 break;
181 case 1:
182 IEEE80211_DEBUG(IEEE80211_DL_HT, "Upper channel\n");
183 break;
184 case 2:
185 IEEE80211_DEBUG(IEEE80211_DL_HT, "Reserved. Eooro!!!\n");
186 break;
187 case 3:
188 IEEE80211_DEBUG(IEEE80211_DL_HT, "Lower Channel\n");
189 break;
190 }
191 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth)?"20Mhz": "40Mhz");
192
193 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tOperation mode for protection = ");
194 switch(pHTInfoEle->OptMode)
195 {
196 case 0:
197 IEEE80211_DEBUG(IEEE80211_DL_HT, "No Protection\n");
198 break;
199 case 1:
200 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT non-member protection mode\n");
201 break;
202 case 2:
203 IEEE80211_DEBUG(IEEE80211_DL_HT, "Suggest to open protection\n");
204 break;
205 case 3:
206 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT mixed mode\n");
207 break;
208 }
209
210 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\
211 pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]);
212}
213
214/*
215* Return: true if station in half n mode and AP supports 40 bw
216*/
217bool IsHTHalfNmode40Bandwidth(struct ieee80211_device* ieee)
218{
219 bool retValue = false;
220 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
221
222 if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
223 retValue = false;
224 else if(pHTInfo->bRegBW40MHz == false) // station supports 40 bw
225 retValue = false;
226 else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)) // station in half n mode
227 retValue = false;
228 else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) // ap support 40 bw
229 retValue = true;
230 else
231 retValue = false;
232
233 return retValue;
234}
235
236bool IsHTHalfNmodeSGI(struct ieee80211_device* ieee, bool is40MHz)
237{
238 bool retValue = false;
239 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
240
241 if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
242 retValue = false;
243 else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)) // station in half n mode
244 retValue = false;
245 else if(is40MHz) // ap support 40 bw
246 {
247 if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) // ap support 40 bw short GI
248 retValue = true;
249 else
250 retValue = false;
251 }
252 else
253 {
254 if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) // ap support 40 bw short GI
255 retValue = true;
256 else
257 retValue = false;
258 }
259
260 return retValue;
261}
262
263u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee, u8 nMcsRate)
264{
265
266 u8 is40MHz;
267 u8 isShortGI;
268
269 is40MHz = (IsHTHalfNmode40Bandwidth(ieee))?1:0;
270 isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz))? 1:0;
271
272 return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
273}
274
275
276u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate)
277{
278 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
279
280 u8 is40MHz = (pHTInfo->bCurBW40MHz)?1:0;
281 u8 isShortGI = (pHTInfo->bCurBW40MHz)?
282 ((pHTInfo->bCurShortGI40MHz)?1:0):
283 ((pHTInfo->bCurShortGI20MHz)?1:0);
284 return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
285}
286
287/********************************************************************************************************************
288 *function: This function returns current datarate.
289 * input: struct ieee80211_device* ieee
290 * u8 nDataRate
291 * output: none
292 * return: tx rate
293 * notice: quite unsure about how to use this function //wb
294 * *****************************************************************************************************************/
295u16 TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate)
296{
297 //PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
298 u16 CCKOFDMRate[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c};
299 u8 is40MHz = 0;
300 u8 isShortGI = 0;
301
302 if(nDataRate < 12)
303 {
304 return CCKOFDMRate[nDataRate];
305 }
306 else
307 {
308 if (nDataRate >= 0x10 && nDataRate <= 0x1f)//if(nDataRate > 11 && nDataRate < 28 )
309 {
310 is40MHz = 0;
311 isShortGI = 0;
312
313 // nDataRate = nDataRate - 12;
314 }
315 else if(nDataRate >=0x20 && nDataRate <= 0x2f ) //(27, 44)
316 {
317 is40MHz = 1;
318 isShortGI = 0;
319
320 //nDataRate = nDataRate - 28;
321 }
322 else if(nDataRate >= 0x30 && nDataRate <= 0x3f ) //(43, 60)
323 {
324 is40MHz = 0;
325 isShortGI = 1;
326
327 //nDataRate = nDataRate - 44;
328 }
329 else if(nDataRate >= 0x40 && nDataRate <= 0x4f ) //(59, 76)
330 {
331 is40MHz = 1;
332 isShortGI = 1;
333
334 //nDataRate = nDataRate - 60;
335 }
336 return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
337 }
338}
339
340
341
342bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
343{
344 bool retValue = false;
345 struct ieee80211_network* net = &ieee->current_network;
346#if 0
347 if(ieee->bHalfNMode == false)
348 retValue = false;
349 else
350#endif
351 if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
352 (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
353 (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
354 (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
355 (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
356 (net->ralink_cap_exist))
357 retValue = true;
358 else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
359 (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
360 (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
361 //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
362 (net->broadcom_cap_exist))
363 retValue = true;
364 else if(net->bssht.bdRT2RTAggregation)
365 retValue = true;
366 else
367 retValue = false;
368
369 return retValue;
370}
371
372/********************************************************************************************************************
373 *function: This function returns peer IOT.
374 * input: struct ieee80211_device* ieee
375 * output: none
376 * return:
377 * notice:
378 * *****************************************************************************************************************/
379void HTIOTPeerDetermine(struct ieee80211_device* ieee)
380{
381 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
382 struct ieee80211_network* net = &ieee->current_network;
383 if(net->bssht.bdRT2RTAggregation)
384 pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
385 else if(net->broadcom_cap_exist){
386 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
387 }
388 else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
389 (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
390 (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)){//||
391 //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ){
392 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
393 }
394 else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
395 (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
396 (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
397 (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
398 (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
399 net->ralink_cap_exist)
400 pHTInfo->IOTPeer = HT_IOT_PEER_RALINK;
401 else if((net->atheros_cap_exist )|| (memcmp(net->bssid, DLINK_ATHEROS, 3) == 0))
402 pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
403 else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0)
404 pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
405 else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
406 net->marvell_cap_exist){
407 pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
408 }
409 else
410 pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
411
412 IEEE80211_DEBUG(IEEE80211_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer);
413}
414/********************************************************************************************************************
415 *function: Check whether driver should declare received rate up to MCS13 only since some chipset is not good
416 * at receiving MCS14~15 frame from some AP.
417 * input: struct ieee80211_device* ieee
418 * u8 * PeerMacAddr
419 * output: none
420 * return: return 1 if driver should declare MCS13 only(otherwise return 0)
421 * *****************************************************************************************************************/
422u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr)
423{
424 u8 ret = 0;
425#if 0
426 // Apply for 819u only
427#if (HAL_CODE_BASE==RTL8192 && DEV_BUS_TYPE==USB_INTERFACE)
428 if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) ||
429 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)
430 )
431 {
432 ret = 1;
433 }
434
435
436 if(pHTInfo->bCurrentRT2RTAggregation)
437 {
438 // The parameter of pHTInfo->bCurrentRT2RTAggregation must be decided previously
439 ret = 1;
440 }
441#endif
442#endif
443 return ret;
444 }
445
446u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_network *network)
447{
448 u8 retValue = 0;
449 //if(network->marvell_cap_exist)
450 if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
451 {
452 retValue = 1;
453 }
454
455 return retValue;
456}
457
458
459/**
460* Function: HTIOTActIsDisableMCS15
461*
462* Overview: Check whether driver should declare capability of receiving MCS15
463*
464* Input:
465* PADAPTER Adapter,
466*
467* Output: None
468* Return: true if driver should disable MCS15
469* 2008.04.15 Emily
470*/
471bool HTIOTActIsDisableMCS15(struct ieee80211_device* ieee)
472{
473 bool retValue = false;
474
475#ifdef TODO
476 // Apply for 819u only
477#if (HAL_CODE_BASE==RTL8192)
478
479#if (DEV_BUS_TYPE == USB_INTERFACE)
480 // Alway disable MCS15 by Jerry Chang's request.by Emily, 2008.04.15
481 retValue = true;
482#elif (DEV_BUS_TYPE == PCI_INTERFACE)
483 // Enable MCS15 if the peer is Cisco AP. by Emily, 2008.05.12
484// if(pBssDesc->bCiscoCapExist)
485// retValue = false;
486// else
487 retValue = false;
488#endif
489#endif
490#endif
491 // Jerry Chang suggest that 8190 1x2 does not need to disable MCS15
492
493 return retValue;
494}
495
496/**
497* Function: HTIOTActIsDisableMCSTwoSpatialStream
498*
499* Overview: Check whether driver should declare capability of receiving All 2 ss packets
500*
501* Input:
502* PADAPTER Adapter,
503*
504* Output: None
505* Return: true if driver should disable all two spatial stream packet
506* 2008.04.21 Emily
507*/
508bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device* ieee, u8 *PeerMacAddr)
509{
510 bool retValue = false;
511
512#ifdef TODO
513 // Apply for 819u only
514//#if (HAL_CODE_BASE==RTL8192)
515
516 //This rule only apply to Belkin(Ralink) AP
517 if(IS_UNDER_11N_AES_MODE(Adapter))
518 {
519 if((PlatformCompareMemory(PeerMacAddr, BELKINF5D8233V1_RALINK, 3)==0) ||
520 (PlatformCompareMemory(PeerMacAddr, PCI_RALINK, 3)==0) ||
521 (PlatformCompareMemory(PeerMacAddr, EDIMAX_RALINK, 3)==0))
522 {
523 //Set True to disable this function. Disable by default, Emily, 2008.04.23
524 retValue = false;
525 }
526 }
527
528//#endif
529#endif
530 return retValue;
531}
532
533/********************************************************************************************************************
534 *function: Check whether driver should disable EDCA turbo mode
535 * input: struct ieee80211_device* ieee
536 * u8* PeerMacAddr
537 * output: none
538 * return: return 1 if driver should disable EDCA turbo mode(otherwise return 0)
539 * *****************************************************************************************************************/
540u8 HTIOTActIsDisableEDCATurbo(struct ieee80211_device* ieee, u8* PeerMacAddr)
541{
542 u8 retValue = false; // default enable EDCA Turbo mode.
543 // Set specific EDCA parameter for different AP in DM handler.
544
545 return retValue;
546#if 0
547 if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0)||
548 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
549 (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
550 (memcmp(PeerMacAddr, NETGEAR834Bv2_BROADCOM, 3)==0))
551
552 {
553 retValue = 1; //Linksys disable EDCA turbo mode
554 }
555
556 return retValue;
557#endif
558}
559
560/********************************************************************************************************************
561 *function: Check whether we need to use OFDM to sned MGNT frame for broadcom AP
562 * input: struct ieee80211_network *network //current network we live
563 * output: none
564 * return: return 1 if true
565 * *****************************************************************************************************************/
566u8 HTIOTActIsMgntUseCCK6M(struct ieee80211_network *network)
567{
568 u8 retValue = 0;
569
570 // 2008/01/25 MH Judeg if we need to use OFDM to sned MGNT frame for broadcom AP.
571 // 2008/01/28 MH We must prevent that we select null bssid to link.
572
573 if(network->broadcom_cap_exist)
574 {
575 retValue = 1;
576 }
577
578 return retValue;
579}
580
581u8 HTIOTActIsCCDFsync(u8* PeerMacAddr)
582{
583 u8 retValue = 0;
584 if( (memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) ||
585 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0) ||
586 (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) ==0))
587 {
588 retValue = 1;
589 }
590
591 return retValue;
592}
593
594//
595// Send null data for to tell AP that we are awake.
596//
597bool
598HTIOTActIsNullDataPowerSaving(struct ieee80211_device* ieee,struct ieee80211_network *network)
599{
600 bool retValue = false;
601
602 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
603 {
604 if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) // ||(pBssDesc->Vender == HT_IOT_PEER_ATHEROS && pBssDesc->SubTypeOfVender == HT_IOT_PEER_ATHEROS_DIR635))
605 return true;
606
607 }
608 return retValue;
609}
610
611void HTResetIOTSetting(
612 PRT_HIGH_THROUGHPUT pHTInfo
613)
614{
615 pHTInfo->IOTAction = 0;
616 pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
617}
618
619
620/********************************************************************************************************************
621 *function: Construct Capablility Element in Beacon... if HTEnable is turned on
622 * input: struct ieee80211_device* ieee
623 * u8* posHTCap //pointer to store Capability Ele
624 * u8* len //store length of CE
625 * u8 IsEncrypt //whether encrypt, needed further
626 * output: none
627 * return: none
628 * notice: posHTCap can't be null and should be initialized before.
629 * *****************************************************************************************************************/
630void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt)
631{
632 PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo;
633 PHT_CAPABILITY_ELE pCapELE = NULL;
634 //u8 bIsDeclareMCS13;
635
636 if ((posHTCap == NULL) || (pHT == NULL))
637 {
638 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n");
639 return;
640 }
641 memset(posHTCap, 0, *len);
642 if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
643 {
644 u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
645 memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap));
646 pCapELE = (PHT_CAPABILITY_ELE)&(posHTCap[4]);
647 }else
648 {
649 pCapELE = (PHT_CAPABILITY_ELE)posHTCap;
650 }
651
652
653 //HT capability info
654 pCapELE->AdvCoding = 0; // This feature is not supported now!!
655 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
656 {
657 pCapELE->ChlWidth = 0;
658 }
659 else
660 {
661 pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0);
662 }
663
664// pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0);
665 pCapELE->MimoPwrSave = pHT->SelfMimoPs;
666 pCapELE->GreenField = 0; // This feature is not supported now!!
667 pCapELE->ShortGI20Mhz = 1; // We can receive Short GI!!
668 pCapELE->ShortGI40Mhz = 1; // We can receive Short GI!!
669 //DbgPrint("TX HT cap/info ele BW=%d SG20=%d SG40=%d\n\r",
670 //pCapELE->ChlWidth, pCapELE->ShortGI20Mhz, pCapELE->ShortGI40Mhz);
671 pCapELE->TxSTBC = 1;
672 pCapELE->RxSTBC = 0;
673 pCapELE->DelayBA = 0; // Do not support now!!
674 pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE>=7935)?1:0;
675 pCapELE->DssCCk = ((pHT->bRegBW40MHz)?(pHT->bRegSuppCCK?1:0):0);
676 pCapELE->PSMP = 0; // Do not support now!!
677 pCapELE->LSigTxopProtect = 0; // Do not support now!!
678
679
680 //MAC HT parameters info
681 // TODO: Nedd to take care of this part
682 IEEE80211_DEBUG(IEEE80211_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
683
684 if( IsEncrypt)
685 {
686 pCapELE->MPDUDensity = 7; // 8us
687 pCapELE->MaxRxAMPDUFactor = 2; // 2 is for 32 K and 3 is 64K
688 }
689 else
690 {
691 pCapELE->MaxRxAMPDUFactor = 3; // 2 is for 32 K and 3 is 64K
692 pCapELE->MPDUDensity = 0; // no density
693 }
694
695 //Supported MCS set
696 memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16);
697 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15)
698 pCapELE->MCS[1] &= 0x7f;
699
700 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14)
701 pCapELE->MCS[1] &= 0xbf;
702
703 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS)
704 pCapELE->MCS[1] &= 0x00;
705
706 // 2008.06.12
707 // For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7.
708 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
709 {
710 int i;
711 for(i = 1; i< 16; i++)
712 pCapELE->MCS[i] = 0;
713 }
714
715 //Extended HT Capability Info
716 memset(&pCapELE->ExtHTCapInfo, 0, 2);
717
718
719 //TXBF Capabilities
720 memset(pCapELE->TxBFCap, 0, 4);
721
722 //Antenna Selection Capabilities
723 pCapELE->ASCap = 0;
724//add 2 to give space for element ID and len when construct frames
725 if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
726 *len = 30 + 2;
727 else
728 *len = 26 + 2;
729}
730/********************************************************************************************************************
731 *function: Construct Information Element in Beacon... if HTEnable is turned on
732 * input: struct ieee80211_device* ieee
733 * u8* posHTCap //pointer to store Information Ele
734 * u8* len //store len of
735 * u8 IsEncrypt //whether encrypt, needed further
736 * output: none
737 * return: none
738 * notice: posHTCap can't be null and be initialized before. only AP and IBSS sta should do this
739 * *****************************************************************************************************************/
740void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 IsEncrypt)
741{
742 PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo;
743 PHT_INFORMATION_ELE pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo;
744 if ((posHTInfo == NULL) || (pHTInfoEle == NULL))
745 {
746 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n");
747 return;
748 }
749
750 memset(posHTInfo, 0, *len);
751 if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported
752 {
753 pHTInfoEle->ControlChl = ieee->current_network.channel;
754 pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
755 (ieee->current_network.channel<=6)?
756 HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
757 pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz;
758 pHTInfoEle->RIFS = 0;
759 pHTInfoEle->PSMPAccessOnly = 0;
760 pHTInfoEle->SrvIntGranularity = 0;
761 pHTInfoEle->OptMode = pHT->CurrentOpMode;
762 pHTInfoEle->NonGFDevPresent = 0;
763 pHTInfoEle->DualBeacon = 0;
764 pHTInfoEle->SecondaryBeacon = 0;
765 pHTInfoEle->LSigTxopProtectFull = 0;
766 pHTInfoEle->PcoActive = 0;
767 pHTInfoEle->PcoPhase = 0;
768
769 memset(pHTInfoEle->BasicMSC, 0, 16);
770
771
772 *len = 22 + 2; //same above
773
774 }
775 else
776 {
777 //STA should not generate High Throughput Information Element
778 *len = 0;
779 }
780}
781
782/*
783 * According to experiment, Realtek AP to STA (based on rtl8190) may achieve best performance
784 * if both STA and AP set limitation of aggregation size to 32K, that is, set AMPDU density to 2
785 * (Ref: IEEE 11n specification). However, if Realtek STA associates to other AP, STA should set
786 * limitation of aggregation size to 8K, otherwise, performance of traffic stream from STA to AP
787 * will be much less than the traffic stream from AP to STA if both of the stream runs concurrently
788 * at the same time.
789 *
790 * Frame Format
791 * Element ID Length OUI Type1 Reserved
792 * 1 byte 1 byte 3 bytes 1 byte 1 byte
793 *
794 * OUI = 0x00, 0xe0, 0x4c,
795 * Type = 0x02
796 * Reserved = 0x00
797 *
798 * 2007.8.21 by Emily
799*/
800/********************************************************************************************************************
801 *function: Construct Information Element in Beacon... in RT2RT condition
802 * input: struct ieee80211_device* ieee
803 * u8* posRT2RTAgg //pointer to store Information Ele
804 * u8* len //store len
805 * output: none
806 * return: none
807 * notice:
808 * *****************************************************************************************************************/
809void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len)
810{
811 if (posRT2RTAgg == NULL) {
812 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n");
813 return;
814 }
815 memset(posRT2RTAgg, 0, *len);
816 *posRT2RTAgg++ = 0x00;
817 *posRT2RTAgg++ = 0xe0;
818 *posRT2RTAgg++ = 0x4c;
819 *posRT2RTAgg++ = 0x02;
820 *posRT2RTAgg++ = 0x01;
821 *posRT2RTAgg = 0x10;//*posRT2RTAgg = 0x02;
822
823 if(ieee->bSupportRemoteWakeUp) {
824 *posRT2RTAgg |= 0x08;//RT_HT_CAP_USE_WOW;
825 }
826
827 *len = 6 + 2;
828 return;
829#ifdef TODO
830#if(HAL_CODE_BASE == RTL8192 && DEV_BUS_TYPE == USB_INTERFACE)
831 /*
832 //Emily. If it is required to Ask Realtek AP to send AMPDU during AES mode, enable this
833 section of code.
834 if(IS_UNDER_11N_AES_MODE(Adapter))
835 {
836 posRT2RTAgg->Octet[5] |=RT_HT_CAP_USE_AMPDU;
837 }else
838 {
839 posRT2RTAgg->Octet[5] &= 0xfb;
840 }
841 */
842
843#else
844 // Do Nothing
845#endif
846
847 posRT2RTAgg->Length = 6;
848#endif
849
850
851
852
853}
854
855
856/********************************************************************************************************************
857 *function: Pick the right Rate Adaptive table to use
858 * input: struct ieee80211_device* ieee
859 * u8* pOperateMCS //A pointer to MCS rate bitmap
860 * return: always we return true
861 * notice:
862 * *****************************************************************************************************************/
863u8 HT_PickMCSRate(struct ieee80211_device* ieee, u8* pOperateMCS)
864{
865 u8 i;
866 if (pOperateMCS == NULL)
867 {
868 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pOperateMCS can't be null in HT_PickMCSRate()\n");
869 return false;
870 }
871
872 switch(ieee->mode)
873 {
874 case IEEE_A:
875 case IEEE_B:
876 case IEEE_G:
877 //legacy rate routine handled at selectedrate
878
879 //no MCS rate
880 for(i=0;i<=15;i++){
881 pOperateMCS[i] = 0;
882 }
883 break;
884
885 case IEEE_N_24G: //assume CCK rate ok
886 case IEEE_N_5G:
887 // Legacy part we only use 6, 5.5,2,1 for N_24G and 6 for N_5G.
888 // Legacy part shall be handled at SelectRateSet().
889
890 //HT part
891 // TODO: may be different if we have different number of antenna
892 pOperateMCS[0] &=RATE_ADPT_1SS_MASK; //support MCS 0~7
893 pOperateMCS[1] &=RATE_ADPT_2SS_MASK;
894 pOperateMCS[3] &=RATE_ADPT_MCS32_MASK;
895 break;
896
897 //should never reach here
898 default:
899
900 break;
901
902 }
903
904 return true;
905}
906
907/*
908* Description:
909* This function will get the highest speed rate in input MCS set.
910*
911* /param Adapter Pionter to Adapter entity
912* pMCSRateSet Pointer to MCS rate bitmap
913* pMCSFilter Pointer to MCS rate filter
914*
915* /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter.
916*
917*/
918/********************************************************************************************************************
919 *function: This function will get the highest speed rate in input MCS set.
920 * input: struct ieee80211_device* ieee
921 * u8* pMCSRateSet //Pointer to MCS rate bitmap
922 * u8* pMCSFilter //Pointer to MCS rate filter
923 * return: Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter
924 * notice:
925 * *****************************************************************************************************************/
926u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter)
927{
928 u8 i, j;
929 u8 bitMap;
930 u8 mcsRate = 0;
931 u8 availableMcsRate[16];
932 if (pMCSRateSet == NULL || pMCSFilter == NULL)
933 {
934 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n");
935 return false;
936 }
937 for(i=0; i<16; i++)
938 availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];
939
940 for(i = 0; i < 16; i++)
941 {
942 if(availableMcsRate[i] != 0)
943 break;
944 }
945 if(i == 16)
946 return false;
947
948 for(i = 0; i < 16; i++)
949 {
950 if(availableMcsRate[i] != 0)
951 {
952 bitMap = availableMcsRate[i];
953 for(j = 0; j < 8; j++)
954 {
955 if((bitMap%2) != 0)
956 {
957 if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate))
958 mcsRate = (8*i+j);
959 }
960 bitMap = bitMap>>1;
961 }
962 }
963 }
964 return (mcsRate|0x80);
965}
966
967
968
969/*
970**
971**1.Filter our operation rate set with AP's rate set
972**2.shall reference channel bandwidth, STBC, Antenna number
973**3.generate rate adative table for firmware
974**David 20060906
975**
976** \pHTSupportedCap: the connected STA's supported rate Capability element
977*/
978u8 HTFilterMCSRate( struct ieee80211_device* ieee, u8* pSupportMCS, u8* pOperateMCS)
979{
980
981 u8 i=0;
982
983 // filter out operational rate set not supported by AP, the lenth of it is 16
984 for(i=0;i<=15;i++){
985 pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i]&pSupportMCS[i];
986 }
987
988
989 // TODO: adjust our operational rate set according to our channel bandwidth, STBC and Antenna number
990
991 // TODO: fill suggested rate adaptive rate index and give firmware info using Tx command packet
992 // we also shall suggested the first start rate set according to our singal strength
993 HT_PickMCSRate(ieee, pOperateMCS);
994
995 // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
996 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
997 pOperateMCS[1] = 0;
998
999 //
1000 // For RTL819X, we support only MCS0~15.
1001 // And also, we do not know how to use MCS32 now.
1002 //
1003 for(i=2; i<=15; i++)
1004 pOperateMCS[i] = 0;
1005
1006 return true;
1007}
1008void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
1009void HTOnAssocRsp(struct ieee80211_device *ieee)
1010{
1011 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1012 PHT_CAPABILITY_ELE pPeerHTCap = NULL;
1013 PHT_INFORMATION_ELE pPeerHTInfo = NULL;
1014 u16 nMaxAMSDUSize = 0;
1015 u8* pMcsFilter = NULL;
1016
1017 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
1018 static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily
1019
1020 if( pHTInfo->bCurrentHTSupport == false )
1021 {
1022 IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n");
1023 return;
1024 }
1025 IEEE80211_DEBUG(IEEE80211_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
1026// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTCapBuf, sizeof(HT_CAPABILITY_ELE));
1027// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTInfoBuf, sizeof(HT_INFORMATION_ELE));
1028
1029// HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq");
1030// HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq");
1031 //
1032 if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap)))
1033 pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
1034 else
1035 pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
1036
1037 if(!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
1038 pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]);
1039 else
1040 pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf);
1041
1042
1043 ////////////////////////////////////////////////////////
1044 // Configurations:
1045 ////////////////////////////////////////////////////////
1046 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE));
1047// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTInfo, sizeof(HT_INFORMATION_ELE));
1048 // Config Supported Channel Width setting
1049 //
1050 HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset));
1051
1052// if(pHTInfo->bCurBW40MHz == true)
1053 pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false);
1054
1055 //
1056 // Update short GI/ long GI setting
1057 //
1058 // TODO:
1059 pHTInfo->bCurShortGI20MHz=
1060 ((pHTInfo->bRegShortGI20MHz)?((pPeerHTCap->ShortGI20Mhz==1)?true:false):false);
1061 pHTInfo->bCurShortGI40MHz=
1062 ((pHTInfo->bRegShortGI40MHz)?((pPeerHTCap->ShortGI40Mhz==1)?true:false):false);
1063
1064 //
1065 // Config TX STBC setting
1066 //
1067 // TODO:
1068
1069 //
1070 // Config DSSS/CCK mode in 40MHz mode
1071 //
1072 // TODO:
1073 pHTInfo->bCurSuppCCK =
1074 ((pHTInfo->bRegSuppCCK)?((pPeerHTCap->DssCCk==1)?true:false):false);
1075
1076
1077 //
1078 // Config and configure A-MSDU setting
1079 //
1080 pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
1081 if (ieee->rtllib_ap_sec_type &&
1082 (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
1083 if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
1084 (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
1085 pHTInfo->bCurrentAMPDUEnable = false;
1086 }
1087
1088
1089 nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
1090
1091 if(pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize )
1092 pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize;
1093 else
1094 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1095
1096
1097 //
1098 // Config A-MPDU setting
1099 //
1100 pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
1101
1102 // <1> Decide AMPDU Factor
1103
1104 // By Emily
1105 if(!pHTInfo->bRegRT2RTAggregation)
1106 {
1107 // Decide AMPDU Factor according to protocol handshake
1108 if(pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor)
1109 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1110 else
1111 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1112
1113 }else
1114 {
1115 // Set MPDU density to 2 to Realtek AP, and set it to 0 for others
1116 // Replace MPDU factor declared in original association response frame format. 2007.08.20 by Emily
1117#if 0
1118 osTmp= PacketGetElement( asocpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE);
1119 if(osTmp.Length >= 5) //00:e0:4c:02:00
1120#endif
1121 if (ieee->current_network.bssht.bdRT2RTAggregation)
1122 {
1123 if( ieee->pairwise_key_type != KEY_TYPE_NA)
1124 // Realtek may set 32k in security mode and 64k for others
1125 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1126 else
1127 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K;
1128 }else
1129 {
1130 if(pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K)
1131 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1132 else
1133 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K;
1134 }
1135 }
1136
1137 // <2> Set AMPDU Minimum MPDU Start Spacing
1138 // 802.11n 3.0 section 9.7d.3
1139#if 1
1140 if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
1141 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1142 else
1143 pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
1144 if(ieee->pairwise_key_type != KEY_TYPE_NA )
1145 pHTInfo->CurrentMPDUDensity = 7; // 8us
1146#else
1147 if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
1148 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1149 else
1150 pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
1151#endif
1152 // Force TX AMSDU
1153
1154 // Lanhsin: mark for tmp to avoid deauth by ap from s3
1155 //if(memcmp(pMgntInfo->Bssid, NETGEAR834Bv2_BROADCOM, 3)==0)
1156 if(0)
1157 {
1158
1159 pHTInfo->bCurrentAMPDUEnable = false;
1160 pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE;
1161 pHTInfo->ForcedAMSDUMaxSize = 7935;
1162
1163 pHTInfo->IOTAction |= HT_IOT_ACT_TX_USE_AMSDU_8K;
1164 }
1165
1166 // Rx Reorder Setting
1167 pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable;
1168
1169 //
1170 // Filter out unsupported HT rate for this AP
1171 // Update RATR table
1172 // This is only for 8190 ,8192 or later product which using firmware to handle rate adaptive mechanism.
1173 //
1174
1175 // Handle Ralink AP bad MCS rate set condition. Joseph.
1176 // This fix the bug of Ralink AP. This may be removed in the future.
1177 if(pPeerHTCap->MCS[0] == 0)
1178 pPeerHTCap->MCS[0] = 0xff;
1179
1180 HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet);
1181
1182 //
1183 // Config MIMO Power Save setting
1184 //
1185 pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave;
1186 if(pHTInfo->PeerMimoPs == MIMO_PS_STATIC)
1187 pMcsFilter = MCS_FILTER_1SS;
1188 else
1189 pMcsFilter = MCS_FILTER_ALL;
1190 //WB add for MCS8 bug
1191// pMcsFilter = MCS_FILTER_1SS;
1192 ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter);
1193 ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
1194
1195 //
1196 // Config current operation mode.
1197 //
1198 pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1199
1200
1201
1202}
1203
1204void HTSetConnectBwModeCallback(struct ieee80211_device* ieee);
1205/********************************************************************************************************************
1206 *function: initialize HT info(struct PRT_HIGH_THROUGHPUT)
1207 * input: struct ieee80211_device* ieee
1208 * output: none
1209 * return: none
1210 * notice: This function is called when * (1) MPInitialization Phase * (2) Receiving of Deauthentication from AP
1211********************************************************************************************************************/
1212// TODO: Should this funciton be called when receiving of Disassociation?
1213void HTInitializeHTInfo(struct ieee80211_device* ieee)
1214{
1215 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1216
1217 //
1218 // These parameters will be reset when receiving deauthentication packet
1219 //
1220 IEEE80211_DEBUG(IEEE80211_DL_HT, "===========>%s()\n", __FUNCTION__);
1221 pHTInfo->bCurrentHTSupport = false;
1222
1223 // 40MHz channel support
1224 pHTInfo->bCurBW40MHz = false;
1225 pHTInfo->bCurTxBW40MHz = false;
1226
1227 // Short GI support
1228 pHTInfo->bCurShortGI20MHz = false;
1229 pHTInfo->bCurShortGI40MHz = false;
1230 pHTInfo->bForcedShortGI = false;
1231
1232 // CCK rate support
1233 // This flag is set to true to support CCK rate by default.
1234 // It will be affected by "pHTInfo->bRegSuppCCK" and AP capabilities only when associate to
1235 // 11N BSS.
1236 pHTInfo->bCurSuppCCK = true;
1237
1238 // AMSDU related
1239 pHTInfo->bCurrent_AMSDU_Support = false;
1240 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1241
1242 // AMPUD related
1243 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1244 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1245
1246
1247
1248 // Initialize all of the parameters related to 11n
1249 memset((void*)(&(pHTInfo->SelfHTCap)), 0, sizeof(pHTInfo->SelfHTCap));
1250 memset((void*)(&(pHTInfo->SelfHTInfo)), 0, sizeof(pHTInfo->SelfHTInfo));
1251 memset((void*)(&(pHTInfo->PeerHTCapBuf)), 0, sizeof(pHTInfo->PeerHTCapBuf));
1252 memset((void*)(&(pHTInfo->PeerHTInfoBuf)), 0, sizeof(pHTInfo->PeerHTInfoBuf));
1253
1254 pHTInfo->bSwBwInProgress = false;
1255 pHTInfo->ChnlOp = CHNLOP_NONE;
1256
1257 // Set default IEEE spec for Draft N
1258 pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE;
1259
1260 // Realtek proprietary aggregation mode
1261 pHTInfo->bCurrentRT2RTAggregation = false;
1262 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1263 pHTInfo->IOTPeer = 0;
1264 pHTInfo->IOTAction = 0;
1265
1266 //MCS rate initialized here
1267 {
1268 u8* RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]);
1269 RegHTSuppRateSets[0] = 0xFF; //support MCS 0~7
1270 RegHTSuppRateSets[1] = 0xFF; //support MCS 8~15
1271 RegHTSuppRateSets[4] = 0x01; //support MCS 32
1272 }
1273}
1274/********************************************************************************************************************
1275 *function: initialize Bss HT structure(struct PBSS_HT)
1276 * input: PBSS_HT pBssHT //to be initialized
1277 * output: none
1278 * return: none
1279 * notice: This function is called when initialize network structure
1280********************************************************************************************************************/
1281void HTInitializeBssDesc(PBSS_HT pBssHT)
1282{
1283
1284 pBssHT->bdSupportHT = false;
1285 memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf));
1286 pBssHT->bdHTCapLen = 0;
1287 memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf));
1288 pBssHT->bdHTInfoLen = 0;
1289
1290 pBssHT->bdHTSpecVer= HT_SPEC_VER_IEEE;
1291
1292 pBssHT->bdRT2RTAggregation = false;
1293 pBssHT->bdRT2RTLongSlotTime = false;
1294}
1295#if 0
1296//below function has merged into ieee80211_network_init() in ieee80211_rx.c
1297void
1298HTParsingHTCapElement(
1299 IN PADAPTER Adapter,
1300 IN OCTET_STRING HTCapIE,
1301 OUT PRT_WLAN_BSS pBssDesc
1302)
1303{
1304 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1305
1306 if( HTCapIE.Length > sizeof(pBssDesc->BssHT.bdHTCapBuf) )
1307 {
1308 RT_TRACE( COMP_HT, DBG_LOUD, ("HTParsingHTCapElement(): HT Capability Element length is too long!\n") );
1309 return;
1310 }
1311
1312 // TODO: Check the correctness of HT Cap
1313 //Print each field in detail. Driver should not print out this message by default
1314 if(!pMgntInfo->mActingAsAp && !pMgntInfo->mAssoc)
1315 HTDebugHTCapability(DBG_TRACE, Adapter, &HTCapIE, (pu8)"HTParsingHTCapElement()");
1316
1317 HTCapIE.Length = HTCapIE.Length > sizeof(pBssDesc->BssHT.bdHTCapBuf)?\
1318 sizeof(pBssDesc->BssHT.bdHTCapBuf):HTCapIE.Length; //prevent from overflow
1319
1320 CopyMem(pBssDesc->BssHT.bdHTCapBuf, HTCapIE.Octet, HTCapIE.Length);
1321 pBssDesc->BssHT.bdHTCapLen = HTCapIE.Length;
1322
1323}
1324
1325
1326void
1327HTParsingHTInfoElement(
1328 PADAPTER Adapter,
1329 OCTET_STRING HTInfoIE,
1330 PRT_WLAN_BSS pBssDesc
1331)
1332{
1333 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1334
1335 if( HTInfoIE.Length > sizeof(pBssDesc->BssHT.bdHTInfoBuf))
1336 {
1337 RT_TRACE( COMP_HT, DBG_LOUD, ("HTParsingHTInfoElement(): HT Information Element length is too long!\n") );
1338 return;
1339 }
1340
1341 // TODO: Check the correctness of HT Info
1342 //Print each field in detail. Driver should not print out this message by default
1343 if(!pMgntInfo->mActingAsAp && !pMgntInfo->mAssoc)
1344 HTDebugHTInfo(DBG_TRACE, Adapter, &HTInfoIE, (pu8)"HTParsingHTInfoElement()");
1345
1346 HTInfoIE.Length = HTInfoIE.Length > sizeof(pBssDesc->BssHT.bdHTInfoBuf)?\
1347 sizeof(pBssDesc->BssHT.bdHTInfoBuf):HTInfoIE.Length; //prevent from overflow
1348
1349 CopyMem( pBssDesc->BssHT.bdHTInfoBuf, HTInfoIE.Octet, HTInfoIE.Length);
1350 pBssDesc->BssHT.bdHTInfoLen = HTInfoIE.Length;
1351}
1352
1353/*
1354 * Get HT related information from beacon and save it in BssDesc
1355 *
1356 * (1) Parse HTCap, and HTInfo, and record whether it is 11n AP
1357 * (2) If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
1358 * (3) Check whether peer is Realtek AP (for Realtek proprietary aggregation mode).
1359 * Input:
1360 * PADAPTER Adapter
1361 *
1362 * Output:
1363 * PRT_TCB BssDesc
1364 *
1365*/
1366void HTGetValueFromBeaconOrProbeRsp(
1367 PADAPTER Adapter,
1368 POCTET_STRING pSRCmmpdu,
1369 PRT_WLAN_BSS bssDesc
1370)
1371{
1372 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1373 PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
1374 OCTET_STRING HTCapIE, HTInfoIE, HTRealtekAgg, mmpdu;
1375 OCTET_STRING BroadcomElement, CiscoElement;
1376
1377 mmpdu.Octet = pSRCmmpdu->Octet;
1378 mmpdu.Length = pSRCmmpdu->Length;
1379
1380 //2Note:
1381 // Mark for IOT testing using Linksys WRT350N, This AP does not contain WMM IE when
1382 // it is configured at pure-N mode.
1383 // if(bssDesc->BssQos.bdQoSMode & QOS_WMM)
1384 //
1385
1386 HTInitializeBssDesc (&bssDesc->BssHT);
1387
1388 //2<1> Parse HTCap, and HTInfo
1389 // Get HT Capability IE: (1) Get IEEE Draft N IE or (2) Get EWC IE
1390 HTCapIE = PacketGetElement(mmpdu, EID_HTCapability, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
1391 if(HTCapIE.Length == 0)
1392 {
1393 HTCapIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_11N_EWC_HT_CAP, OUI_SUBTYPE_DONT_CARE);
1394 if(HTCapIE.Length != 0)
1395 bssDesc->BssHT.bdHTSpecVer= HT_SPEC_VER_EWC;
1396 }
1397 if(HTCapIE.Length != 0)
1398 HTParsingHTCapElement(Adapter, HTCapIE, bssDesc);
1399
1400 // Get HT Information IE: (1) Get IEEE Draft N IE or (2) Get EWC IE
1401 HTInfoIE = PacketGetElement(mmpdu, EID_HTInfo, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
1402 if(HTInfoIE.Length == 0)
1403 {
1404 HTInfoIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_11N_EWC_HT_INFO, OUI_SUBTYPE_DONT_CARE);
1405 if(HTInfoIE.Length != 0)
1406 bssDesc->BssHT.bdHTSpecVer = HT_SPEC_VER_EWC;
1407 }
1408 if(HTInfoIE.Length != 0)
1409 HTParsingHTInfoElement(Adapter, HTInfoIE, bssDesc);
1410
1411 //2<2>If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
1412 if(HTCapIE.Length != 0)
1413 {
1414 bssDesc->BssHT.bdSupportHT = true;
1415 if(bssDesc->BssQos.bdQoSMode == QOS_DISABLE)
1416 QosSetLegacyWMMParamWithHT(Adapter, bssDesc);
1417 }
1418 else
1419 {
1420 bssDesc->BssHT.bdSupportHT = false;
1421 }
1422
1423 //2<3>Check whether the peer is Realtek AP/STA
1424 if(pHTInfo->bRegRT2RTAggregation)
1425 {
1426 if(bssDesc->BssHT.bdSupportHT)
1427 {
1428 HTRealtekAgg = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE);
1429 if(HTRealtekAgg.Length >=5 )
1430 {
1431 bssDesc->BssHT.bdRT2RTAggregation = true;
1432
1433 if((HTRealtekAgg.Octet[4]==1) && (HTRealtekAgg.Octet[5] & 0x02))
1434 bssDesc->BssHT.bdRT2RTLongSlotTime = true;
1435 }
1436 }
1437 }
1438
1439 //
1440 // 2008/01/25 MH Get Broadcom AP IE for manamgent frame CCK rate problem.
1441 // AP can not receive CCK managemtn from from 92E.
1442 //
1443
1444 // Initialize every new bss broadcom cap exist as false..
1445 bssDesc->bBroadcomCapExist= false;
1446
1447 if(HTCapIE.Length != 0 || HTInfoIE.Length != 0)
1448 {
1449 u4Byte Length = 0;
1450
1451 FillOctetString(BroadcomElement, NULL, 0);
1452
1453 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_1, OUI_SUBTYPE_DONT_CARE);
1454 Length += BroadcomElement.Length;
1455 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_2, OUI_SUBTYPE_DONT_CARE);
1456 Length += BroadcomElement.Length;
1457 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_3, OUI_SUBTYPE_DONT_CARE);
1458 Length += BroadcomElement.Length;
1459
1460 if(Length > 0)
1461 bssDesc->bBroadcomCapExist = true;
1462 }
1463
1464
1465 // For Cisco IOT issue
1466 CiscoElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_CISCO_IE, OUI_SUBTYPE_DONT_CARE);
1467 if(CiscoElement.Length != 0){ // 3: 0x00, 0x40, 0x96 ....
1468 bssDesc->bCiscoCapExist = true;
1469 }else{
1470 bssDesc->bCiscoCapExist = false;
1471 }
1472}
1473
1474
1475#endif
1476/********************************************************************************************************************
1477 *function: initialize Bss HT structure(struct PBSS_HT)
1478 * input: struct ieee80211_device *ieee
1479 * struct ieee80211_network *pNetwork //usually current network we are live in
1480 * output: none
1481 * return: none
1482 * notice: This function should ONLY be called before association
1483********************************************************************************************************************/
1484void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork)
1485{
1486 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1487// u16 nMaxAMSDUSize;
1488// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1489// PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1490// u8* pMcsFilter;
1491 u8 bIOTAction = 0;
1492
1493 //
1494 // Save Peer Setting before Association
1495 //
1496 IEEE80211_DEBUG(IEEE80211_DL_HT, "==============>%s()\n", __FUNCTION__);
1497 /*unmark bEnableHT flag here is the same reason why unmarked in function ieee80211_softmac_new_net. WB 2008.09.10*/
1498// if( pHTInfo->bEnableHT && pNetwork->bssht.bdSupportHT)
1499 if (pNetwork->bssht.bdSupportHT)
1500 {
1501 pHTInfo->bCurrentHTSupport = true;
1502 pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
1503
1504 // Save HTCap and HTInfo information Element
1505 if(pNetwork->bssht.bdHTCapLen > 0 && pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf))
1506 memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen);
1507
1508 if(pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf))
1509 memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen);
1510
1511 // Check whether RT to RT aggregation mode is enabled
1512 if(pHTInfo->bRegRT2RTAggregation)
1513 {
1514 pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation;
1515 pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime;
1516 }
1517 else
1518 {
1519 pHTInfo->bCurrentRT2RTAggregation = false;
1520 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1521 }
1522
1523 // Determine the IOT Peer Vendor.
1524 HTIOTPeerDetermine(ieee);
1525
1526 // Decide IOT Action
1527 // Must be called after the parameter of pHTInfo->bCurrentRT2RTAggregation is decided
1528 pHTInfo->IOTAction = 0;
1529 bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
1530 if(bIOTAction)
1531 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
1532 bIOTAction = HTIOTActIsForcedCTS2Self(ieee, pNetwork);
1533 if(bIOTAction)
1534 pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
1535
1536 bIOTAction = HTIOTActIsDisableMCS15(ieee);
1537 if(bIOTAction)
1538 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15;
1539
1540 bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee, pNetwork->bssid);
1541 if(bIOTAction)
1542 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS;
1543
1544
1545 bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid);
1546 if(bIOTAction)
1547 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO;
1548
1549 bIOTAction = HTIOTActIsMgntUseCCK6M(pNetwork);
1550 if(bIOTAction)
1551 pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M;
1552
1553 bIOTAction = HTIOTActIsCCDFsync(pNetwork->bssid);
1554 if(bIOTAction)
1555 pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
1556
1557 bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
1558 if(bIOTAction)
1559 pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
1560
1561 }
1562 else
1563 {
1564 pHTInfo->bCurrentHTSupport = false;
1565 pHTInfo->bCurrentRT2RTAggregation = false;
1566 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1567
1568 pHTInfo->IOTAction = 0;
1569 }
1570
1571}
1572
1573void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork)
1574{
1575 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1576// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1577 PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1578
1579 if(pHTInfo->bCurrentHTSupport)
1580 {
1581 //
1582 // Config current operation mode.
1583 //
1584 if(pNetwork->bssht.bdHTInfoLen != 0)
1585 pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1586
1587 //
1588 // <TODO: Config according to OBSS non-HT STA present!!>
1589 //
1590 }
1591}
1592
1593void HTUseDefaultSetting(struct ieee80211_device* ieee)
1594{
1595 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1596// u8 regBwOpMode;
1597
1598 if(pHTInfo->bEnableHT)
1599 {
1600 pHTInfo->bCurrentHTSupport = true;
1601
1602 pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK;
1603
1604 pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz;
1605
1606 pHTInfo->bCurShortGI20MHz= pHTInfo->bRegShortGI20MHz;
1607
1608 pHTInfo->bCurShortGI40MHz= pHTInfo->bRegShortGI40MHz;
1609
1610 pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
1611
1612 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1613
1614 pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
1615
1616 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1617
1618 pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
1619
1620 // Set BWOpMode register
1621
1622 //update RATR index0
1623 HTFilterMCSRate(ieee, ieee->Regdot11HTOperationalRateSet, ieee->dot11HTOperationalRateSet);
1624 //function below is not implemented at all. WB
1625#ifdef TODO
1626 Adapter->HalFunc.InitHalRATRTableHandler( Adapter, &pMgntInfo->dot11OperationalRateSet, pMgntInfo->dot11HTOperationalRateSet);
1627#endif
1628 ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, MCS_FILTER_ALL);
1629 ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
1630
1631 }
1632 else
1633 {
1634 pHTInfo->bCurrentHTSupport = false;
1635 }
1636}
1637/********************************************************************************************************************
1638 *function: check whether HT control field exists
1639 * input: struct ieee80211_device *ieee
1640 * u8* pFrame //coming skb->data
1641 * output: none
1642 * return: return true if HT control field exists(false otherwise)
1643 * notice:
1644********************************************************************************************************************/
1645u8 HTCCheck(struct ieee80211_device* ieee, u8* pFrame)
1646{
1647 if(ieee->pHTInfo->bCurrentHTSupport)
1648 {
1649 if( (IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1)
1650 {
1651 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT CONTROL FILED EXIST!!\n");
1652 return true;
1653 }
1654 }
1655 return false;
1656}
1657
1658//
1659// This function set bandwidth mode in protocol layer.
1660//
1661void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset)
1662{
1663 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1664// u32 flags = 0;
1665
1666 if(pHTInfo->bRegBW40MHz == false)
1667 return;
1668
1669
1670
1671 // To reduce dummy operation
1672// if((pHTInfo->bCurBW40MHz==false && Bandwidth==HT_CHANNEL_WIDTH_20) ||
1673// (pHTInfo->bCurBW40MHz==true && Bandwidth==HT_CHANNEL_WIDTH_20_40 && Offset==pHTInfo->CurSTAExtChnlOffset))
1674// return;
1675
1676// spin_lock_irqsave(&(ieee->bw_spinlock), flags);
1677 if(pHTInfo->bSwBwInProgress) {
1678// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1679 return;
1680 }
1681 //if in half N mode, set to 20M bandwidth please 09.08.2008 WB.
1682 if (Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)))
1683 {
1684 // Handle Illegal extension channel offset!!
1685 if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER)
1686 Offset = HT_EXTCHNL_OFFSET_NO_EXT;
1687 if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) {
1688 pHTInfo->bCurBW40MHz = true;
1689 pHTInfo->CurSTAExtChnlOffset = Offset;
1690 } else {
1691 pHTInfo->bCurBW40MHz = false;
1692 pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1693 }
1694 } else {
1695 pHTInfo->bCurBW40MHz = false;
1696 pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1697 }
1698
1699 pHTInfo->bSwBwInProgress = true;
1700
1701 // TODO: 2007.7.13 by Emily Wait 2000ms in order to guarantee that switching
1702 // bandwidth is executed after scan is finished. It is a temporal solution
1703 // because software should ganrantee the last operation of switching bandwidth
1704 // is executed properlly.
1705 HTSetConnectBwModeCallback(ieee);
1706
1707// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1708}
1709
1710void HTSetConnectBwModeCallback(struct ieee80211_device* ieee)
1711{
1712 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1713
1714 IEEE80211_DEBUG(IEEE80211_DL_HT, "======>%s()\n", __FUNCTION__);
1715
1716 if(pHTInfo->bCurBW40MHz)
1717 {
1718 if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER)
1719 ieee->set_chan(ieee, ieee->current_network.channel+2);
1720 else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER)
1721 ieee->set_chan(ieee, ieee->current_network.channel-2);
1722 else
1723 ieee->set_chan(ieee, ieee->current_network.channel);
1724
1725 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
1726 } else {
1727 ieee->set_chan(ieee, ieee->current_network.channel);
1728 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1729 }
1730
1731 pHTInfo->bSwBwInProgress = false;
1732}
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h
new file mode 100644
index 00000000000..d4565ecc7ab
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h
@@ -0,0 +1,582 @@
1#ifndef __INC_QOS_TYPE_H
2#define __INC_QOS_TYPE_H
3
4#define BIT0 0x00000001
5#define BIT1 0x00000002
6#define BIT2 0x00000004
7#define BIT3 0x00000008
8#define BIT4 0x00000010
9#define BIT5 0x00000020
10#define BIT6 0x00000040
11#define BIT7 0x00000080
12#define BIT8 0x00000100
13#define BIT9 0x00000200
14#define BIT10 0x00000400
15#define BIT11 0x00000800
16#define BIT12 0x00001000
17#define BIT13 0x00002000
18#define BIT14 0x00004000
19#define BIT15 0x00008000
20#define BIT16 0x00010000
21#define BIT17 0x00020000
22#define BIT18 0x00040000
23#define BIT19 0x00080000
24#define BIT20 0x00100000
25#define BIT21 0x00200000
26#define BIT22 0x00400000
27#define BIT23 0x00800000
28#define BIT24 0x01000000
29#define BIT25 0x02000000
30#define BIT26 0x04000000
31#define BIT27 0x08000000
32#define BIT28 0x10000000
33#define BIT29 0x20000000
34#define BIT30 0x40000000
35#define BIT31 0x80000000
36
37#define MAX_WMMELE_LENGTH 64
38
39//
40// QoS mode.
41// enum 0, 1, 2, 4: since we can use the OR(|) operation.
42//
43// QOS_MODE is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
44//typedef enum _QOS_MODE{
45// QOS_DISABLE = 0,
46// QOS_WMM = 1,
47// QOS_EDCA = 2,
48// QOS_HCCA = 4,
49//}QOS_MODE,*PQOS_MODE;
50//
51typedef u32 QOS_MODE, *PQOS_MODE;
52#define QOS_DISABLE 0
53#define QOS_WMM 1
54#define QOS_WMMSA 2
55#define QOS_EDCA 4
56#define QOS_HCCA 8
57#define QOS_WMM_UAPSD 16 //WMM Power Save, 2006-06-14 Isaiah
58
59#define AC_PARAM_SIZE 4
60#define WMM_PARAM_ELE_BODY_LEN 18
61
62//
63// QoS ACK Policy Field Values
64// Ref: WMM spec 2.1.6: QoS Control Field, p.10.
65//
66typedef enum _ACK_POLICY{
67 eAckPlc0_ACK = 0x00,
68 eAckPlc1_NoACK = 0x01,
69}ACK_POLICY,*PACK_POLICY;
70
71#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE))
72
73//
74// QoS Control Field
75// Ref:
76// 1. WMM spec 2.1.6: QoS Control Field, p.9.
77// 2. 802.11e/D13.0 7.1.3.5, p.26.
78//
79typedef union _QOS_CTRL_FIELD{
80 u8 charData[2];
81 u16 shortData;
82
83 // WMM spec
84 struct
85 {
86 u8 UP:3;
87 u8 usRsvd1:1;
88 u8 EOSP:1;
89 u8 AckPolicy:2;
90 u8 usRsvd2:1;
91 u8 ucRsvdByte;
92 }WMM;
93
94 // 802.11e: QoS data type frame sent by non-AP QSTAs.
95 struct
96 {
97 u8 TID:4;
98 u8 bIsQsize:1;// 0: BIT[8:15] is TXOP Duration Requested, 1: BIT[8:15] is Queue Size.
99 u8 AckPolicy:2;
100 u8 usRsvd:1;
101 u8 TxopOrQsize; // (BIT4=0)TXOP Duration Requested or (BIT4=1)Queue Size.
102 }BySta;
103
104 // 802.11e: QoS data, QoS Null, and QoS Data+CF-Ack frames sent by HC.
105 struct
106 {
107 u8 TID:4;
108 u8 EOSP:1;
109 u8 AckPolicy:2;
110 u8 usRsvd:1;
111 u8 PSBufState; // QAP PS Buffer State.
112 }ByHc_Data;
113
114 // 802.11e: QoS (+) CF-Poll frames sent by HC.
115 struct
116 {
117 u8 TID:4;
118 u8 EOSP:1;
119 u8 AckPolicy:2;
120 u8 usRsvd:1;
121 u8 TxopLimit; // TXOP Limit.
122 }ByHc_CFP;
123
124}QOS_CTRL_FIELD, *PQOS_CTRL_FIELD;
125
126
127//
128// QoS Info Field
129// Ref:
130// 1. WMM spec 2.2.1: WME Information Element, p.11.
131// 2. 8185 QoS code: QOS_INFO [def. in QoS_mp.h]
132//
133typedef union _QOS_INFO_FIELD{
134 u8 charData;
135
136 struct
137 {
138 u8 ucParameterSetCount:4;
139 u8 ucReserved:4;
140 }WMM;
141
142 struct
143 {
144 //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
145 u8 ucAC_VO_UAPSD:1;
146 u8 ucAC_VI_UAPSD:1;
147 u8 ucAC_BE_UAPSD:1;
148 u8 ucAC_BK_UAPSD:1;
149 u8 ucReserved1:1;
150 u8 ucMaxSPLen:2;
151 u8 ucReserved2:1;
152
153 }ByWmmPsSta;
154
155 struct
156 {
157 //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
158 u8 ucParameterSetCount:4;
159 u8 ucReserved:3;
160 u8 ucApUapsd:1;
161 }ByWmmPsAp;
162
163 struct
164 {
165 u8 ucAC3_UAPSD:1;
166 u8 ucAC2_UAPSD:1;
167 u8 ucAC1_UAPSD:1;
168 u8 ucAC0_UAPSD:1;
169 u8 ucQAck:1;
170 u8 ucMaxSPLen:2;
171 u8 ucMoreDataAck:1;
172 } By11eSta;
173
174 struct
175 {
176 u8 ucParameterSetCount:4;
177 u8 ucQAck:1;
178 u8 ucQueueReq:1;
179 u8 ucTXOPReq:1;
180 u8 ucReserved:1;
181 } By11eAp;
182
183 struct
184 {
185 u8 ucReserved1:4;
186 u8 ucQAck:1;
187 u8 ucReserved2:2;
188 u8 ucMoreDataAck:1;
189 } ByWmmsaSta;
190
191 struct
192 {
193 u8 ucReserved1:4;
194 u8 ucQAck:1;
195 u8 ucQueueReq:1;
196 u8 ucTXOPReq:1;
197 u8 ucReserved2:1;
198 } ByWmmsaAp;
199
200 struct
201 {
202 u8 ucAC3_UAPSD:1;
203 u8 ucAC2_UAPSD:1;
204 u8 ucAC1_UAPSD:1;
205 u8 ucAC0_UAPSD:1;
206 u8 ucQAck:1;
207 u8 ucMaxSPLen:2;
208 u8 ucMoreDataAck:1;
209 } ByAllSta;
210
211 struct
212 {
213 u8 ucParameterSetCount:4;
214 u8 ucQAck:1;
215 u8 ucQueueReq:1;
216 u8 ucTXOPReq:1;
217 u8 ucApUapsd:1;
218 } ByAllAp;
219
220}QOS_INFO_FIELD, *PQOS_INFO_FIELD;
221
222//
223// ACI to AC coding.
224// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
225//
226// AC_CODING is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
227//typedef enum _AC_CODING{
228// AC0_BE = 0, // ACI: 0x00 // Best Effort
229// AC1_BK = 1, // ACI: 0x01 // Background
230// AC2_VI = 2, // ACI: 0x10 // Video
231// AC3_VO = 3, // ACI: 0x11 // Voice
232// AC_MAX = 4, // Max: define total number; Should not to be used as a real enum.
233//}AC_CODING,*PAC_CODING;
234//
235typedef u32 AC_CODING;
236#define AC0_BE 0 // ACI: 0x00 // Best Effort
237#define AC1_BK 1 // ACI: 0x01 // Background
238#define AC2_VI 2 // ACI: 0x10 // Video
239#define AC3_VO 3 // ACI: 0x11 // Voice
240#define AC_MAX 4 // Max: define total number; Should not to be used as a real enum.
241
242//
243// ACI/AIFSN Field.
244// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
245//
246typedef union _ACI_AIFSN{
247 u8 charData;
248
249 struct
250 {
251 u8 AIFSN:4;
252 u8 ACM:1;
253 u8 ACI:2;
254 u8 Reserved:1;
255 }f; // Field
256}ACI_AIFSN, *PACI_AIFSN;
257
258//
259// ECWmin/ECWmax field.
260// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
261//
262typedef union _ECW{
263 u8 charData;
264 struct
265 {
266 u8 ECWmin:4;
267 u8 ECWmax:4;
268 }f; // Field
269}ECW, *PECW;
270
271//
272// AC Parameters Record Format.
273// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
274//
275typedef union _AC_PARAM{
276 u32 longData;
277 u8 charData[4];
278
279 struct
280 {
281 ACI_AIFSN AciAifsn;
282 ECW Ecw;
283 u16 TXOPLimit;
284 }f; // Field
285}AC_PARAM, *PAC_PARAM;
286
287
288
289//
290// QoS element subtype
291//
292typedef enum _QOS_ELE_SUBTYPE{
293 QOSELE_TYPE_INFO = 0x00, // 0x00: Information element
294 QOSELE_TYPE_PARAM = 0x01, // 0x01: parameter element
295}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE;
296
297
298//
299// Direction Field Values.
300// Ref: WMM spec 2.2.11: WME TSPEC Element, p.18.
301//
302typedef enum _DIRECTION_VALUE{
303 DIR_UP = 0, // 0x00 // UpLink
304 DIR_DOWN = 1, // 0x01 // DownLink
305 DIR_DIRECT = 2, // 0x10 // DirectLink
306 DIR_BI_DIR = 3, // 0x11 // Bi-Direction
307}DIRECTION_VALUE,*PDIRECTION_VALUE;
308
309
310//
311// TS Info field in WMM TSPEC Element.
312// Ref:
313// 1. WMM spec 2.2.11: WME TSPEC Element, p.18.
314// 2. 8185 QoS code: QOS_TSINFO [def. in QoS_mp.h]
315//
316typedef union _QOS_TSINFO{
317 u8 charData[3];
318 struct {
319 u8 ucTrafficType:1; //WMM is reserved
320 u8 ucTSID:4;
321 u8 ucDirection:2;
322 u8 ucAccessPolicy:2; //WMM: bit8=0, bit7=1
323 u8 ucAggregation:1; //WMM is reserved
324 u8 ucPSB:1; //WMMSA is APSD
325 u8 ucUP:3;
326 u8 ucTSInfoAckPolicy:2; //WMM is reserved
327 u8 ucSchedule:1; //WMM is reserved
328 u8 ucReserved:7;
329 }field;
330}QOS_TSINFO, *PQOS_TSINFO;
331
332//
333// WMM TSPEC Body.
334// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
335//
336typedef union _TSPEC_BODY{
337 u8 charData[55];
338
339 struct
340 {
341 QOS_TSINFO TSInfo; //u8 TSInfo[3];
342 u16 NominalMSDUsize;
343 u16 MaxMSDUsize;
344 u32 MinServiceItv;
345 u32 MaxServiceItv;
346 u32 InactivityItv;
347 u32 SuspenItv;
348 u32 ServiceStartTime;
349 u32 MinDataRate;
350 u32 MeanDataRate;
351 u32 PeakDataRate;
352 u32 MaxBurstSize;
353 u32 DelayBound;
354 u32 MinPhyRate;
355 u16 SurplusBandwidthAllowance;
356 u16 MediumTime;
357 } f; // Field
358}TSPEC_BODY, *PTSPEC_BODY;
359
360
361//
362// WMM TSPEC Element.
363// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
364//
365typedef struct _WMM_TSPEC{
366 u8 ID;
367 u8 Length;
368 u8 OUI[3];
369 u8 OUI_Type;
370 u8 OUI_SubType;
371 u8 Version;
372 TSPEC_BODY Body;
373} WMM_TSPEC, *PWMM_TSPEC;
374
375//
376// ACM implementation method.
377// Annie, 2005-12-13.
378//
379typedef enum _ACM_METHOD{
380 eAcmWay0_SwAndHw = 0, // By SW and HW.
381 eAcmWay1_HW = 1, // By HW.
382 eAcmWay2_SW = 2, // By SW.
383}ACM_METHOD,*PACM_METHOD;
384
385
386typedef struct _ACM{
387// u8 RegEnableACM;
388 u64 UsedTime;
389 u64 MediumTime;
390 u8 HwAcmCtl; // TRUE: UsedTime exceed => Do NOT USE this AC. It wll be written to ACM_CONTROL(0xBF BIT 0/1/2 in 8185B).
391}ACM, *PACM;
392
393typedef u8 AC_UAPSD, *PAC_UAPSD;
394
395#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
396#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
397
398#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
399#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
400
401#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
402#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
403
404#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
405#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
406
407
408//typedef struct _TCLASS{
409// TODO
410//} TCLASS, *PTCLASS;
411typedef union _QOS_TCLAS{
412
413 struct _TYPE_GENERAL{
414 u8 Priority;
415 u8 ClassifierType;
416 u8 Mask;
417 } TYPE_GENERAL;
418
419 struct _TYPE0_ETH{
420 u8 Priority;
421 u8 ClassifierType;
422 u8 Mask;
423 u8 SrcAddr[6];
424 u8 DstAddr[6];
425 u16 Type;
426 } TYPE0_ETH;
427
428 struct _TYPE1_IPV4{
429 u8 Priority;
430 u8 ClassifierType;
431 u8 Mask;
432 u8 Version;
433 u8 SrcIP[4];
434 u8 DstIP[4];
435 u16 SrcPort;
436 u16 DstPort;
437 u8 DSCP;
438 u8 Protocol;
439 u8 Reserved;
440 } TYPE1_IPV4;
441
442 struct _TYPE1_IPV6{
443 u8 Priority;
444 u8 ClassifierType;
445 u8 Mask;
446 u8 Version;
447 u8 SrcIP[16];
448 u8 DstIP[16];
449 u16 SrcPort;
450 u16 DstPort;
451 u8 FlowLabel[3];
452 } TYPE1_IPV6;
453
454 struct _TYPE2_8021Q{
455 u8 Priority;
456 u8 ClassifierType;
457 u8 Mask;
458 u16 TagType;
459 } TYPE2_8021Q;
460} QOS_TCLAS, *PQOS_TCLAS;
461
462//typedef struct _WMM_TSTREAM{
463//
464//- TSPEC
465//- AC (which to mapping)
466//} WMM_TSTREAM, *PWMM_TSTREAM;
467typedef struct _QOS_TSTREAM{
468 u8 AC;
469 WMM_TSPEC TSpec;
470 QOS_TCLAS TClass;
471} QOS_TSTREAM, *PQOS_TSTREAM;
472
473//typedef struct _U_APSD{
474//- TriggerEnable [4]
475//- MaxSPLength
476//- HighestAcBuffered
477//} U_APSD, *PU_APSD;
478
479//joseph TODO:
480// UAPSD function should be implemented by 2 data structure
481// "Qos control field" and "Qos info field"
482//typedef struct _QOS_UAPSD{
483// u8 bTriggerEnable[4];
484// u8 MaxSPLength;
485// u8 HighestBufAC;
486//} QOS_UAPSD, *PQOS_APSD;
487
488//----------------------------------------------------------------------------
489// 802.11 Management frame Status Code field
490//----------------------------------------------------------------------------
491typedef struct _OCTET_STRING{
492 u8 *Octet;
493 u16 Length;
494}OCTET_STRING, *POCTET_STRING;
495
496//
497// STA QoS data.
498// Ref: DOT11_QOS in 8185 code. [def. in QoS_mp.h]
499//
500typedef struct _STA_QOS{
501 //DECLARE_RT_OBJECT(STA_QOS);
502 u8 WMMIEBuf[MAX_WMMELE_LENGTH];
503 u8* WMMIE;
504
505 // Part 1. Self QoS Mode.
506 QOS_MODE QosCapability; //QoS Capability, 2006-06-14 Isaiah
507 QOS_MODE CurrentQosMode;
508
509 // For WMM Power Save Mode :
510 // ACs are trigger/delivery enabled or legacy power save enabled. 2006-06-13 Isaiah
511 AC_UAPSD b4ac_Uapsd; //VoUapsd(bit0), ViUapsd(bit1), BkUapsd(bit2), BeUapsd(bit3),
512 AC_UAPSD Curr4acUapsd;
513 u8 bInServicePeriod;
514 u8 MaxSPLength;
515 int NumBcnBeforeTrigger;
516
517 // Part 2. EDCA Parameter (perAC)
518 u8 * pWMMInfoEle;
519 u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE];
520 u8 WMMPELength;
521
522 // <Bruce_Note>
523 //2 ToDo: remove the Qos Info Field and replace it by the above WMM Info element.
524 // By Bruce, 2008-01-30.
525 // Part 2. EDCA Parameter (perAC)
526 QOS_INFO_FIELD QosInfoField_STA; // Maintained by STA
527 QOS_INFO_FIELD QosInfoField_AP; // Retrieved from AP
528
529 AC_PARAM CurAcParameters[4];
530
531 // Part 3. ACM
532 ACM acm[4];
533 ACM_METHOD AcmMethod;
534
535 // Part 4. Per TID (Part 5: TCLASS will be described by TStream)
536 QOS_TSTREAM TStream[16];
537 WMM_TSPEC TSpec;
538
539 u32 QBssWirelessMode;
540
541 // No Ack Setting
542 u8 bNoAck;
543
544 // Enable/Disable Rx immediate BA capability.
545 u8 bEnableRxImmBA;
546
547}STA_QOS, *PSTA_QOS;
548
549//
550// BSS QOS data.
551// Ref: BssDscr in 8185 code. [def. in BssDscr.h]
552//
553typedef struct _BSS_QOS{
554 QOS_MODE bdQoSMode;
555
556 u8 bdWMMIEBuf[MAX_WMMELE_LENGTH];
557 u8* bdWMMIE;
558
559 QOS_ELE_SUBTYPE EleSubType;
560
561 u8 * pWMMInfoEle;
562 u8 * pWMMParamEle;
563
564 QOS_INFO_FIELD QosInfoField;
565 AC_PARAM AcParameter[4];
566}BSS_QOS, *PBSS_QOS;
567
568
569//
570// Ref: sQoSCtlLng and QoSCtl definition in 8185 QoS code.
571//#define QoSCtl (( (Adapter->bRegQoS) && (Adapter->dot11QoS.QoSMode &(QOS_EDCA|QOS_HCCA)) ) ?sQoSCtlLng:0)
572//
573#define sQoSCtlLng 2
574#define QOS_CTRL_LEN(_QosMode) ((_QosMode > QOS_DISABLE)? sQoSCtlLng : 0)
575
576
577//Added by joseph
578//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
579//#define UP2AC(up) ((up<3)?((up==0)?1:0):(up>>1))
580#define IsACValid(ac) ((ac<=7 )?true:false )
581
582#endif // #ifndef __INC_QOS_TYPE_H
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h
new file mode 100644
index 00000000000..e7e26fd9639
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h
@@ -0,0 +1,56 @@
1#ifndef _TSTYPE_H_
2#define _TSTYPE_H_
3#include "rtl819x_Qos.h"
4#define TS_SETUP_TIMEOUT 60 // In millisecond
5#define TS_INACT_TIMEOUT 60
6#define TS_ADDBA_DELAY 60
7
8#define TOTAL_TS_NUM 16
9#define TCLAS_NUM 4
10
11// This define the Tx/Rx directions
12typedef enum _TR_SELECT {
13 TX_DIR = 0,
14 RX_DIR = 1,
15} TR_SELECT, *PTR_SELECT;
16
17typedef struct _TS_COMMON_INFO{
18 struct list_head List;
19 struct timer_list SetupTimer;
20 struct timer_list InactTimer;
21 u8 Addr[6];
22 TSPEC_BODY TSpec;
23 QOS_TCLAS TClass[TCLAS_NUM];
24 u8 TClasProc;
25 u8 TClasNum;
26} TS_COMMON_INFO, *PTS_COMMON_INFO;
27
28typedef struct _TX_TS_RECORD{
29 TS_COMMON_INFO TsCommonInfo;
30 u16 TxCurSeq;
31 BA_RECORD TxPendingBARecord; // For BA Originator
32 BA_RECORD TxAdmittedBARecord; // For BA Originator
33// QOS_DL_RECORD DLRecord;
34 u8 bAddBaReqInProgress;
35 u8 bAddBaReqDelayed;
36 u8 bUsingBa;
37 struct timer_list TsAddBaTimer;
38 u8 num;
39} TX_TS_RECORD, *PTX_TS_RECORD;
40
41typedef struct _RX_TS_RECORD {
42 TS_COMMON_INFO TsCommonInfo;
43 u16 RxIndicateSeq;
44 u16 RxTimeoutIndicateSeq;
45 struct list_head RxPendingPktList;
46 struct timer_list RxPktPendingTimer;
47 BA_RECORD RxAdmittedBARecord; // For BA Recipient
48 u16 RxLastSeqNum;
49 u8 RxLastFragNum;
50 u8 num;
51// QOS_DL_RECORD DLRecord;
52} RX_TS_RECORD, *PRX_TS_RECORD;
53
54
55#endif
56
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
new file mode 100644
index 00000000000..ad6872dcf1c
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
@@ -0,0 +1,627 @@
1#include "ieee80211.h"
2#include <linux/etherdevice.h>
3#include <linux/slab.h>
4#include "rtl819x_TS.h"
5
6void TsSetupTimeOut(unsigned long data)
7{
8 // Not implement yet
9 // This is used for WMMSA and ACM , that would send ADDTSReq frame.
10}
11
12void TsInactTimeout(unsigned long data)
13{
14 // Not implement yet
15 // This is used for WMMSA and ACM.
16 // This function would be call when TS is no Tx/Rx for some period of time.
17}
18
19/********************************************************************************************************************
20 *function: I still not understand this function, so wait for further implementation
21 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
22 * return: NULL
23 * notice:
24********************************************************************************************************************/
25void RxPktPendingTimeout(unsigned long data)
26{
27 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
28 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
29
30 PRX_REORDER_ENTRY pReorderEntry = NULL;
31
32 //u32 flags = 0;
33 unsigned long flags = 0;
34 struct ieee80211_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
35 u8 index = 0;
36 bool bPktInBuf = false;
37
38
39 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
40 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
41 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__FUNCTION__);
42 if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
43 {
44 // Indicate the pending packets sequentially according to SeqNum until meet the gap.
45 while(!list_empty(&pRxTs->RxPendingPktList))
46 {
47 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
48 if(index == 0)
49 pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
50
51 if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ||
52 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) )
53 {
54 list_del_init(&pReorderEntry->List);
55
56 if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
57 pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;
58
59 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
60 stats_IndicateArray[index] = pReorderEntry->prxb;
61 index++;
62
63 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
64 }
65 else
66 {
67 bPktInBuf = true;
68 break;
69 }
70 }
71 }
72
73 if(index>0)
74 {
75 // Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now.
76 pRxTs->RxTimeoutIndicateSeq = 0xffff;
77
78 // Indicate packets
79 if(index > REORDER_WIN_SIZE){
80 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
81 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
82 return;
83 }
84 ieee80211_indicate_packets(ieee, stats_IndicateArray, index);
85 }
86
87 if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
88 {
89 pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
90 mod_timer(&pRxTs->RxPktPendingTimer, jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime));
91 }
92 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
93 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
94}
95
96/********************************************************************************************************************
97 *function: Add BA timer function
98 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
99 * return: NULL
100 * notice:
101********************************************************************************************************************/
102void TsAddBaProcess(unsigned long data)
103{
104 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
105 u8 num = pTxTs->num;
106 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
107
108 TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
109 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
110}
111
112
113void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo)
114{
115 memset(pTsCommonInfo->Addr, 0, 6);
116 memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
117 memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
118 pTsCommonInfo->TClasProc = 0;
119 pTsCommonInfo->TClasNum = 0;
120}
121
122void ResetTxTsEntry(PTX_TS_RECORD pTS)
123{
124 ResetTsCommonInfo(&pTS->TsCommonInfo);
125 pTS->TxCurSeq = 0;
126 pTS->bAddBaReqInProgress = false;
127 pTS->bAddBaReqDelayed = false;
128 pTS->bUsingBa = false;
129 ResetBaEntry(&pTS->TxAdmittedBARecord); //For BA Originator
130 ResetBaEntry(&pTS->TxPendingBARecord);
131}
132
133void ResetRxTsEntry(PRX_TS_RECORD pTS)
134{
135 ResetTsCommonInfo(&pTS->TsCommonInfo);
136 pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!!
137 pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!!
138 ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recipient
139}
140
141void TSInitialize(struct ieee80211_device *ieee)
142{
143 PTX_TS_RECORD pTxTS = ieee->TxTsRecord;
144 PRX_TS_RECORD pRxTS = ieee->RxTsRecord;
145 PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry;
146 u8 count = 0;
147 IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __FUNCTION__);
148 // Initialize Tx TS related info.
149 INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
150 INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
151 INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
152
153 for(count = 0; count < TOTAL_TS_NUM; count++)
154 {
155 //
156 pTxTS->num = count;
157 // The timers for the operation of Traffic Stream and Block Ack.
158 // DLS related timer will be add here in the future!!
159 init_timer(&pTxTS->TsCommonInfo.SetupTimer);
160 pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS;
161 pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
162
163 init_timer(&pTxTS->TsCommonInfo.InactTimer);
164 pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS;
165 pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
166
167 init_timer(&pTxTS->TsAddBaTimer);
168 pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS;
169 pTxTS->TsAddBaTimer.function = TsAddBaProcess;
170
171 init_timer(&pTxTS->TxPendingBARecord.Timer);
172 pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS;
173 pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut;
174
175 init_timer(&pTxTS->TxAdmittedBARecord.Timer);
176 pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS;
177 pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout;
178
179 ResetTxTsEntry(pTxTS);
180 list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List);
181 pTxTS++;
182 }
183
184 // Initialize Rx TS related info.
185 INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
186 INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
187 INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
188 for(count = 0; count < TOTAL_TS_NUM; count++)
189 {
190 pRxTS->num = count;
191 INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
192
193 init_timer(&pRxTS->TsCommonInfo.SetupTimer);
194 pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS;
195 pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
196
197 init_timer(&pRxTS->TsCommonInfo.InactTimer);
198 pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS;
199 pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
200
201 init_timer(&pRxTS->RxAdmittedBARecord.Timer);
202 pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS;
203 pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout;
204
205 init_timer(&pRxTS->RxPktPendingTimer);
206 pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS;
207 pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout;
208
209 ResetRxTsEntry(pRxTS);
210 list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
211 pRxTS++;
212 }
213 // Initialize unused Rx Reorder List.
214 INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
215//#ifdef TO_DO_LIST
216 for(count = 0; count < REORDER_ENTRY_NUM; count++)
217 {
218 list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
219 if(count == (REORDER_ENTRY_NUM-1))
220 break;
221 pRxReorderEntry = &ieee->RxReorderEntry[count+1];
222 }
223//#endif
224
225}
226
227void AdmitTS(struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime)
228{
229 del_timer_sync(&pTsCommonInfo->SetupTimer);
230 del_timer_sync(&pTsCommonInfo->InactTimer);
231
232 if(InactTime!=0)
233 mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime));
234}
235
236
237PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect)
238{
239 //DIRECTION_VALUE dir;
240 u8 dir;
241 bool search_dir[4] = {0, 0, 0, 0};
242 struct list_head* psearch_list; //FIXME
243 PTS_COMMON_INFO pRet = NULL;
244 if(ieee->iw_mode == IW_MODE_MASTER) //ap mode
245 {
246 if(TxRxSelect == TX_DIR)
247 {
248 search_dir[DIR_DOWN] = true;
249 search_dir[DIR_BI_DIR]= true;
250 }
251 else
252 {
253 search_dir[DIR_UP] = true;
254 search_dir[DIR_BI_DIR]= true;
255 }
256 }
257 else if(ieee->iw_mode == IW_MODE_ADHOC)
258 {
259 if(TxRxSelect == TX_DIR)
260 search_dir[DIR_UP] = true;
261 else
262 search_dir[DIR_DOWN] = true;
263 }
264 else
265 {
266 if(TxRxSelect == TX_DIR)
267 {
268 search_dir[DIR_UP] = true;
269 search_dir[DIR_BI_DIR]= true;
270 search_dir[DIR_DIRECT]= true;
271 }
272 else
273 {
274 search_dir[DIR_DOWN] = true;
275 search_dir[DIR_BI_DIR]= true;
276 search_dir[DIR_DIRECT]= true;
277 }
278 }
279
280 if(TxRxSelect == TX_DIR)
281 psearch_list = &ieee->Tx_TS_Admit_List;
282 else
283 psearch_list = &ieee->Rx_TS_Admit_List;
284
285 //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
286 for(dir = 0; dir <= DIR_BI_DIR; dir++)
287 {
288 if(search_dir[dir] ==false )
289 continue;
290 list_for_each_entry(pRet, psearch_list, List){
291 // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
292 if (memcmp(pRet->Addr, Addr, 6) == 0)
293 if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
294 if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
295 {
296 break;
297 }
298
299 }
300 if(&pRet->List != psearch_list)
301 break;
302 }
303
304 if(&pRet->List != psearch_list){
305 return pRet ;
306 }
307 else
308 return NULL;
309}
310
311void MakeTSEntry(
312 PTS_COMMON_INFO pTsCommonInfo,
313 u8* Addr,
314 PTSPEC_BODY pTSPEC,
315 PQOS_TCLAS pTCLAS,
316 u8 TCLAS_Num,
317 u8 TCLAS_Proc
318 )
319{
320 u8 count;
321
322 if(pTsCommonInfo == NULL)
323 return;
324
325 memcpy(pTsCommonInfo->Addr, Addr, 6);
326
327 if(pTSPEC != NULL)
328 memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY));
329
330 for(count = 0; count < TCLAS_Num; count++)
331 memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS));
332
333 pTsCommonInfo->TClasProc = TCLAS_Proc;
334 pTsCommonInfo->TClasNum = TCLAS_Num;
335}
336
337
338bool GetTs(
339 struct ieee80211_device* ieee,
340 PTS_COMMON_INFO *ppTS,
341 u8* Addr,
342 u8 TID,
343 TR_SELECT TxRxSelect, //Rx:1, Tx:0
344 bool bAddNewTs
345 )
346{
347 u8 UP = 0;
348 //
349 // We do not build any TS for Broadcast or Multicast stream.
350 // So reject these kinds of search here.
351 //
352 if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
353 {
354 IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
355 return false;
356 }
357
358 if (ieee->current_network.qos_data.supported == 0)
359 UP = 0;
360 else
361 {
362 // In WMM case: we use 4 TID only
363 if (!IsACValid(TID))
364 {
365 IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __FUNCTION__, TID);
366 return false;
367 }
368
369 switch(TID)
370 {
371 case 0:
372 case 3:
373 UP = 0;
374 break;
375
376 case 1:
377 case 2:
378 UP = 2;
379 break;
380
381 case 4:
382 case 5:
383 UP = 5;
384 break;
385
386 case 6:
387 case 7:
388 UP = 7;
389 break;
390 }
391 }
392
393 *ppTS = SearchAdmitTRStream(
394 ieee,
395 Addr,
396 UP,
397 TxRxSelect);
398 if(*ppTS != NULL)
399 {
400 return true;
401 }
402 else
403 {
404 if(bAddNewTs == false)
405 {
406 IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
407 return false;
408 }
409 else
410 {
411 //
412 // Create a new Traffic stream for current Tx/Rx
413 // This is for EDCA and WMM to add a new TS.
414 // For HCCA or WMMSA, TS cannot be addmit without negotiation.
415 //
416 TSPEC_BODY TSpec;
417 PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo;
418 struct list_head* pUnusedList =
419 (TxRxSelect == TX_DIR)?
420 (&ieee->Tx_TS_Unused_List):
421 (&ieee->Rx_TS_Unused_List);
422
423 struct list_head* pAddmitList =
424 (TxRxSelect == TX_DIR)?
425 (&ieee->Tx_TS_Admit_List):
426 (&ieee->Rx_TS_Admit_List);
427
428 DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)?
429 ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
430 ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
431 IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
432 if(!list_empty(pUnusedList))
433 {
434 (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
435 list_del_init(&(*ppTS)->List);
436 if(TxRxSelect==TX_DIR)
437 {
438 PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
439 ResetTxTsEntry(tmp);
440 }
441 else{
442 PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);
443 ResetRxTsEntry(tmp);
444 }
445
446 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
447 // Prepare TS Info releated field
448 pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
449 pTSInfo->field.ucTSID = UP; // TSID
450 pTSInfo->field.ucDirection = Dir; // Direction: if there is DirectLink, this need additional consideration.
451 pTSInfo->field.ucAccessPolicy = 1; // Access policy
452 pTSInfo->field.ucAggregation = 0; // Aggregation
453 pTSInfo->field.ucPSB = 0; // Aggregation
454 pTSInfo->field.ucUP = UP; // User priority
455 pTSInfo->field.ucTSInfoAckPolicy = 0; // Ack policy
456 pTSInfo->field.ucSchedule = 0; // Schedule
457
458 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
459 AdmitTS(ieee, *ppTS, 0);
460 list_add_tail(&((*ppTS)->List), pAddmitList);
461 // if there is DirectLink, we need to do additional operation here!!
462
463 return true;
464 }
465 else
466 {
467 IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __FUNCTION__);
468 return false;
469 }
470 }
471 }
472}
473
474void RemoveTsEntry(
475 struct ieee80211_device* ieee,
476 PTS_COMMON_INFO pTs,
477 TR_SELECT TxRxSelect
478 )
479{
480 //u32 flags = 0;
481 unsigned long flags = 0;
482 del_timer_sync(&pTs->SetupTimer);
483 del_timer_sync(&pTs->InactTimer);
484 TsInitDelBA(ieee, pTs, TxRxSelect);
485
486 if(TxRxSelect == RX_DIR)
487 {
488//#ifdef TO_DO_LIST
489 PRX_REORDER_ENTRY pRxReorderEntry;
490 PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs;
491 if(timer_pending(&pRxTS->RxPktPendingTimer))
492 del_timer_sync(&pRxTS->RxPktPendingTimer);
493
494 while(!list_empty(&pRxTS->RxPendingPktList))
495 {
496 // PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
497 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
498 //pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
499 pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
500 list_del_init(&pRxReorderEntry->List);
501 {
502 int i = 0;
503 struct ieee80211_rxb * prxb = pRxReorderEntry->prxb;
504 if (unlikely(!prxb))
505 {
506 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
507 return;
508 }
509 for(i =0; i < prxb->nr_subframes; i++) {
510 dev_kfree_skb(prxb->subframes[i]);
511 }
512 kfree(prxb);
513 prxb = NULL;
514 }
515 list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
516 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
517 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
518 }
519
520//#endif
521 }
522 else
523 {
524 PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
525 del_timer_sync(&pTxTS->TsAddBaTimer);
526 }
527}
528
529void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
530{
531 PTS_COMMON_INFO pTS, pTmpTS;
532
533 printk("===========>RemovePeerTS,%pM\n", Addr);
534 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
535 {
536 if (memcmp(pTS->Addr, Addr, 6) == 0)
537 {
538 RemoveTsEntry(ieee, pTS, TX_DIR);
539 list_del_init(&pTS->List);
540 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
541 }
542 }
543
544 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
545 {
546 if (memcmp(pTS->Addr, Addr, 6) == 0)
547 {
548 printk("====>remove Tx_TS_admin_list\n");
549 RemoveTsEntry(ieee, pTS, TX_DIR);
550 list_del_init(&pTS->List);
551 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
552 }
553 }
554
555 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
556 {
557 if (memcmp(pTS->Addr, Addr, 6) == 0)
558 {
559 RemoveTsEntry(ieee, pTS, RX_DIR);
560 list_del_init(&pTS->List);
561 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
562 }
563 }
564
565 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
566 {
567 if (memcmp(pTS->Addr, Addr, 6) == 0)
568 {
569 RemoveTsEntry(ieee, pTS, RX_DIR);
570 list_del_init(&pTS->List);
571 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
572 }
573 }
574}
575
576void RemoveAllTS(struct ieee80211_device* ieee)
577{
578 PTS_COMMON_INFO pTS, pTmpTS;
579
580 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
581 {
582 RemoveTsEntry(ieee, pTS, TX_DIR);
583 list_del_init(&pTS->List);
584 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
585 }
586
587 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
588 {
589 RemoveTsEntry(ieee, pTS, TX_DIR);
590 list_del_init(&pTS->List);
591 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
592 }
593
594 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
595 {
596 RemoveTsEntry(ieee, pTS, RX_DIR);
597 list_del_init(&pTS->List);
598 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
599 }
600
601 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
602 {
603 RemoveTsEntry(ieee, pTS, RX_DIR);
604 list_del_init(&pTS->List);
605 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
606 }
607}
608
609void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS)
610{
611 if(pTxTS->bAddBaReqInProgress == false)
612 {
613 pTxTS->bAddBaReqInProgress = true;
614 if(pTxTS->bAddBaReqDelayed)
615 {
616 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
617 mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY));
618 }
619 else
620 {
621 IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
622 mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks
623 }
624 }
625 else
626 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
627}
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h b/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h
new file mode 100644
index 00000000000..ccf6ae76357
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h
@@ -0,0 +1,399 @@
1/*
2 * Scatterlist Cryptographic API.
3 *
4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
5 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
6 *
7 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
8 * and Nettle, by Niels Mé°ˆler.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 *
15 */
16#ifndef _LINUX_CRYPTO_H
17#define _LINUX_CRYPTO_H
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/list.h>
23#include <linux/string.h>
24#include <asm/page.h>
25#include <asm/errno.h>
26
27#define crypto_register_alg crypto_register_alg_rsl
28#define crypto_unregister_alg crypto_unregister_alg_rsl
29#define crypto_alloc_tfm crypto_alloc_tfm_rsl
30#define crypto_free_tfm crypto_free_tfm_rsl
31#define crypto_alg_available crypto_alg_available_rsl
32
33/*
34 * Algorithm masks and types.
35 */
36#define CRYPTO_ALG_TYPE_MASK 0x000000ff
37#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
38#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
39#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
40
41/*
42 * Transform masks and values (for crt_flags).
43 */
44#define CRYPTO_TFM_MODE_MASK 0x000000ff
45#define CRYPTO_TFM_REQ_MASK 0x000fff00
46#define CRYPTO_TFM_RES_MASK 0xfff00000
47
48#define CRYPTO_TFM_MODE_ECB 0x00000001
49#define CRYPTO_TFM_MODE_CBC 0x00000002
50#define CRYPTO_TFM_MODE_CFB 0x00000004
51#define CRYPTO_TFM_MODE_CTR 0x00000008
52
53#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
54#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
55#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
56#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
57#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
58#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
59
60/*
61 * Miscellaneous stuff.
62 */
63#define CRYPTO_UNSPEC 0
64#define CRYPTO_MAX_ALG_NAME 64
65
66struct scatterlist;
67
68/*
69 * Algorithms: modular crypto algorithm implementations, managed
70 * via crypto_register_alg() and crypto_unregister_alg().
71 */
72struct cipher_alg {
73 unsigned int cia_min_keysize;
74 unsigned int cia_max_keysize;
75 int (*cia_setkey)(void *ctx, const u8 *key,
76 unsigned int keylen, u32 *flags);
77 void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
78 void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
79};
80
81struct digest_alg {
82 unsigned int dia_digestsize;
83 void (*dia_init)(void *ctx);
84 void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
85 void (*dia_final)(void *ctx, u8 *out);
86 int (*dia_setkey)(void *ctx, const u8 *key,
87 unsigned int keylen, u32 *flags);
88};
89
90struct compress_alg {
91 int (*coa_init)(void *ctx);
92 void (*coa_exit)(void *ctx);
93 int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
94 u8 *dst, unsigned int *dlen);
95 int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
96 u8 *dst, unsigned int *dlen);
97};
98
99#define cra_cipher cra_u.cipher
100#define cra_digest cra_u.digest
101#define cra_compress cra_u.compress
102
103struct crypto_alg {
104 struct list_head cra_list;
105 u32 cra_flags;
106 unsigned int cra_blocksize;
107 unsigned int cra_ctxsize;
108 const char cra_name[CRYPTO_MAX_ALG_NAME];
109
110 union {
111 struct cipher_alg cipher;
112 struct digest_alg digest;
113 struct compress_alg compress;
114 } cra_u;
115
116 struct module *cra_module;
117};
118
119/*
120 * Algorithm registration interface.
121 */
122int crypto_register_alg(struct crypto_alg *alg);
123int crypto_unregister_alg(struct crypto_alg *alg);
124
125/*
126 * Algorithm query interface.
127 */
128int crypto_alg_available(const char *name, u32 flags);
129
130/*
131 * Transforms: user-instantiated objects which encapsulate algorithms
132 * and core processing logic. Managed via crypto_alloc_tfm() and
133 * crypto_free_tfm(), as well as the various helpers below.
134 */
135struct crypto_tfm;
136
137struct cipher_tfm {
138 void *cit_iv;
139 unsigned int cit_ivsize;
140 u32 cit_mode;
141 int (*cit_setkey)(struct crypto_tfm *tfm,
142 const u8 *key, unsigned int keylen);
143 int (*cit_encrypt)(struct crypto_tfm *tfm,
144 struct scatterlist *dst,
145 struct scatterlist *src,
146 unsigned int nbytes);
147 int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
148 struct scatterlist *dst,
149 struct scatterlist *src,
150 unsigned int nbytes, u8 *iv);
151 int (*cit_decrypt)(struct crypto_tfm *tfm,
152 struct scatterlist *dst,
153 struct scatterlist *src,
154 unsigned int nbytes);
155 int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
156 struct scatterlist *dst,
157 struct scatterlist *src,
158 unsigned int nbytes, u8 *iv);
159 void (*cit_xor_block)(u8 *dst, const u8 *src);
160};
161
162struct digest_tfm {
163 void (*dit_init)(struct crypto_tfm *tfm);
164 void (*dit_update)(struct crypto_tfm *tfm,
165 struct scatterlist *sg, unsigned int nsg);
166 void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
167 void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
168 unsigned int nsg, u8 *out);
169 int (*dit_setkey)(struct crypto_tfm *tfm,
170 const u8 *key, unsigned int keylen);
171#ifdef CONFIG_CRYPTO_HMAC
172 void *dit_hmac_block;
173#endif
174};
175
176struct compress_tfm {
177 int (*cot_compress)(struct crypto_tfm *tfm,
178 const u8 *src, unsigned int slen,
179 u8 *dst, unsigned int *dlen);
180 int (*cot_decompress)(struct crypto_tfm *tfm,
181 const u8 *src, unsigned int slen,
182 u8 *dst, unsigned int *dlen);
183};
184
185#define crt_cipher crt_u.cipher
186#define crt_digest crt_u.digest
187#define crt_compress crt_u.compress
188
189struct crypto_tfm {
190
191 u32 crt_flags;
192
193 union {
194 struct cipher_tfm cipher;
195 struct digest_tfm digest;
196 struct compress_tfm compress;
197 } crt_u;
198
199 struct crypto_alg *__crt_alg;
200};
201
202/*
203 * Transform user interface.
204 */
205
206/*
207 * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
208 * If that fails and the kernel supports dynamically loadable modules, it
209 * will then attempt to load a module of the same name or alias. A refcount
210 * is grabbed on the algorithm which is then associated with the new transform.
211 *
212 * crypto_free_tfm() frees up the transform and any associated resources,
213 * then drops the refcount on the associated algorithm.
214 */
215struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
216void crypto_free_tfm(struct crypto_tfm *tfm);
217
218/*
219 * Transform helpers which query the underlying algorithm.
220 */
221static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
222{
223 return tfm->__crt_alg->cra_name;
224}
225
226static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
227{
228 struct crypto_alg *alg = tfm->__crt_alg;
229
230 if (alg->cra_module)
231 return alg->cra_module->name;
232 else
233 return NULL;
234}
235
236static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
237{
238 return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
239}
240
241static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
242{
243 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
244 return tfm->__crt_alg->cra_cipher.cia_min_keysize;
245}
246
247static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
248{
249 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
250 return tfm->__crt_alg->cra_cipher.cia_max_keysize;
251}
252
253static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
254{
255 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
256 return tfm->crt_cipher.cit_ivsize;
257}
258
259static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
260{
261 return tfm->__crt_alg->cra_blocksize;
262}
263
264static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
265{
266 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
267 return tfm->__crt_alg->cra_digest.dia_digestsize;
268}
269
270/*
271 * API wrappers.
272 */
273static inline void crypto_digest_init(struct crypto_tfm *tfm)
274{
275 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
276 tfm->crt_digest.dit_init(tfm);
277}
278
279static inline void crypto_digest_update(struct crypto_tfm *tfm,
280 struct scatterlist *sg,
281 unsigned int nsg)
282{
283 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
284 tfm->crt_digest.dit_update(tfm, sg, nsg);
285}
286
287static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
288{
289 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
290 tfm->crt_digest.dit_final(tfm, out);
291}
292
293static inline void crypto_digest_digest(struct crypto_tfm *tfm,
294 struct scatterlist *sg,
295 unsigned int nsg, u8 *out)
296{
297 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
298 tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
299}
300
301static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
302 const u8 *key, unsigned int keylen)
303{
304 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
305 if (tfm->crt_digest.dit_setkey == NULL)
306 return -ENOSYS;
307 return tfm->crt_digest.dit_setkey(tfm, key, keylen);
308}
309
310static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
311 const u8 *key, unsigned int keylen)
312{
313 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
314 return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
315}
316
317static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
318 struct scatterlist *dst,
319 struct scatterlist *src,
320 unsigned int nbytes)
321{
322 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
323 return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
324}
325
326static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
327 struct scatterlist *dst,
328 struct scatterlist *src,
329 unsigned int nbytes, u8 *iv)
330{
331 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
332 BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
333 return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
334}
335
336static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
337 struct scatterlist *dst,
338 struct scatterlist *src,
339 unsigned int nbytes)
340{
341 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
342 return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
343}
344
345static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
346 struct scatterlist *dst,
347 struct scatterlist *src,
348 unsigned int nbytes, u8 *iv)
349{
350 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
351 BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
352 return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
353}
354
355static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
356 const u8 *src, unsigned int len)
357{
358 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
359 memcpy(tfm->crt_cipher.cit_iv, src, len);
360}
361
362static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
363 u8 *dst, unsigned int len)
364{
365 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
366 memcpy(dst, tfm->crt_cipher.cit_iv, len);
367}
368
369static inline int crypto_comp_compress(struct crypto_tfm *tfm,
370 const u8 *src, unsigned int slen,
371 u8 *dst, unsigned int *dlen)
372{
373 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
374 return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
375}
376
377static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
378 const u8 *src, unsigned int slen,
379 u8 *dst, unsigned int *dlen)
380{
381 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
382 return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
383}
384
385/*
386 * HMAC support.
387 */
388#ifdef CONFIG_CRYPTO_HMAC
389void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
390void crypto_hmac_update(struct crypto_tfm *tfm,
391 struct scatterlist *sg, unsigned int nsg);
392void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
393 unsigned int *keylen, u8 *out);
394void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
395 struct scatterlist *sg, unsigned int nsg, u8 *out);
396#endif /* CONFIG_CRYPTO_HMAC */
397
398#endif /* _LINUX_CRYPTO_H */
399