blob: 7f7c13aaf6b0691d7666291fb958c53fd4bab09e [file] [log] [blame]
Forest Bond92b96792009-06-13 07:38:31 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: rxtx.c
20 *
21 * Purpose: handle WMAC/802.3/802.11 rx & tx functions
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: May 20, 2003
26 *
27 * Functions:
Gilles Espinassef77f13e2010-03-29 15:41:47 +020028 * s_vGenerateTxParameter - Generate tx dma required parameter.
Forest Bond92b96792009-06-13 07:38:31 -040029 * s_vGenerateMACHeader - Translate 802.3 to 802.11 header
30 * csBeacon_xmit - beacon tx function
31 * csMgmt_xmit - management tx function
32 * s_uGetDataDuration - get tx data required duration
33 * s_uFillDataHead- fulfill tx data duration header
Gilles Espinassef77f13e2010-03-29 15:41:47 +020034 * s_uGetRTSCTSDuration- get rtx/cts required duration
Forest Bond92b96792009-06-13 07:38:31 -040035 * s_uGetRTSCTSRsvTime- get rts/cts reserved time
36 * s_uGetTxRsvTime- get frame reserved time
37 * s_vFillCTSHead- fulfill CTS ctl header
Gilles Espinassef77f13e2010-03-29 15:41:47 +020038 * s_vFillFragParameter- Set fragment ctl parameter.
Forest Bond92b96792009-06-13 07:38:31 -040039 * s_vFillRTSHead- fulfill RTS ctl header
40 * s_vFillTxKey- fulfill tx encrypt key
41 * s_vSWencryption- Software encrypt header
42 * vDMA0_tx_80211- tx 802.11 frame via dma0
43 * vGenerateFIFOHeader- Generate tx FIFO ctl header
44 *
45 * Revision History:
46 *
47 */
48
Forest Bond92b96792009-06-13 07:38:31 -040049#include "device.h"
Forest Bond92b96792009-06-13 07:38:31 -040050#include "rxtx.h"
Forest Bond92b96792009-06-13 07:38:31 -040051#include "tether.h"
Forest Bond92b96792009-06-13 07:38:31 -040052#include "card.h"
Forest Bond92b96792009-06-13 07:38:31 -040053#include "bssdb.h"
Forest Bond92b96792009-06-13 07:38:31 -040054#include "mac.h"
Forest Bond92b96792009-06-13 07:38:31 -040055#include "michael.h"
Forest Bond92b96792009-06-13 07:38:31 -040056#include "tkip.h"
Forest Bond92b96792009-06-13 07:38:31 -040057#include "wctl.h"
Forest Bond92b96792009-06-13 07:38:31 -040058#include "rf.h"
Forest Bond92b96792009-06-13 07:38:31 -040059#include "datarate.h"
Forest Bond92b96792009-06-13 07:38:31 -040060#include "usbpipe.h"
Forest Bond92b96792009-06-13 07:38:31 -040061#include "iocmd.h"
Jim Lieb9d26d602009-08-12 14:54:08 -070062
Mariano Reingart4a499de2010-10-29 19:15:26 -030063static int msglevel = MSG_LEVEL_INFO;
Forest Bond92b96792009-06-13 07:38:31 -040064
Valentina Manea3b138852013-11-04 10:44:02 +020065static const u16 wTimeStampOff[2][MAX_RATE] = {
Forest Bond92b96792009-06-13 07:38:31 -040066 {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
67 {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
68 };
69
Valentina Manea3b138852013-11-04 10:44:02 +020070static const u16 wFB_Opt0[2][5] = {
Forest Bond92b96792009-06-13 07:38:31 -040071 {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
72 {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
73 };
Valentina Manea3b138852013-11-04 10:44:02 +020074static const u16 wFB_Opt1[2][5] = {
Forest Bond92b96792009-06-13 07:38:31 -040075 {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
76 {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
77 };
78
Forest Bond92b96792009-06-13 07:38:31 -040079#define RTSDUR_BB 0
80#define RTSDUR_BA 1
81#define RTSDUR_AA 2
82#define CTSDUR_BA 3
83#define RTSDUR_BA_F0 4
84#define RTSDUR_AA_F0 5
85#define RTSDUR_BA_F1 6
86#define RTSDUR_AA_F1 7
87#define CTSDUR_BA_F0 8
88#define CTSDUR_BA_F1 9
89#define DATADUR_B 10
90#define DATADUR_A 11
91#define DATADUR_A_F0 12
92#define DATADUR_A_F1 13
93
Malcolm Priestleyd56131d2013-01-17 23:15:22 +000094static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
95 u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -040096
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +000097static struct vnt_usb_send_context *s_vGetFreeContext(struct vnt_private *);
Malcolm Priestleyd56131d2013-01-17 23:15:22 +000098
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +010099static u16 s_vGenerateTxParameter(struct vnt_usb_send_context *tx_context,
Malcolm Priestley8e344c82013-09-17 19:58:11 +0100100 u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
Malcolm Priestleyfa575602013-09-26 19:00:41 +0100101 struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
Malcolm Priestley05cc6172014-04-30 21:31:12 +0100102 int bNeedACK, struct ethhdr *psEthHeader, bool need_rts);
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000103
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000104static void s_vGenerateMACHeader(struct vnt_private *pDevice,
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100105 struct ieee80211_hdr *pMACHeader, u16 wDuration,
106 struct ethhdr *psEthHeader, int bNeedEncrypt, u16 wFragType,
107 u32 uFragIdx);
Forest Bond92b96792009-06-13 07:38:31 -0400108
Malcolm Priestley3695c462014-05-31 13:34:59 +0100109static void s_vFillTxKey(struct vnt_usb_send_context *tx_context,
Malcolm Priestley3ba09382013-10-15 21:41:38 +0100110 struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead,
Malcolm Priestley3695c462014-05-31 13:34:59 +0100111 PSKeyItem pTransmitKey, u16 wPayloadLen, struct vnt_mic_hdr *mic_hdr);
Forest Bond92b96792009-06-13 07:38:31 -0400112
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000113static void s_vSWencryption(struct vnt_private *pDevice,
114 PSKeyItem pTransmitKey, u8 *pbyPayloadHead, u16 wPayloadSize);
Forest Bond92b96792009-06-13 07:38:31 -0400115
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000116static unsigned int s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType,
117 u32 cbFrameLength, u16 wRate, int bNeedAck);
Forest Bond92b96792009-06-13 07:38:31 -0400118
Malcolm Priestley20338012014-03-18 19:25:08 +0000119static __le16 s_uGetRTSCTSRsvTime(struct vnt_private *priv,
Malcolm Priestley3b6cee7be2014-05-25 21:36:27 +0100120 u8 rsv_type, u8 pkt_type, u32 frame_length, u16 current_rate);
Forest Bond92b96792009-06-13 07:38:31 -0400121
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100122static u16 s_vFillCTSHead(struct vnt_usb_send_context *tx_context,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100123 u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
124 int bNeedAck, u16 wCurrentRate, u8 byFBOption);
Forest Bond92b96792009-06-13 07:38:31 -0400125
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100126static u16 s_vFillRTSHead(struct vnt_usb_send_context *tx_context, u8 byPktType,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100127 union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
Andres Moreceb8c5d2013-03-18 20:33:49 -0500128 struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption);
Forest Bond92b96792009-06-13 07:38:31 -0400129
Malcolm Priestley5abe3d62014-03-18 19:25:06 +0000130static __le16 s_uGetDataDuration(struct vnt_private *pDevice,
Malcolm Priestley3ed210e2013-08-07 21:28:45 +0100131 u8 byPktType, int bNeedAck);
Forest Bond92b96792009-06-13 07:38:31 -0400132
Malcolm Priestley7f591a12014-03-18 19:25:05 +0000133static __le16 s_uGetRTSCTSDuration(struct vnt_private *pDevice,
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000134 u8 byDurType, u32 cbFrameLength, u8 byPktType, u16 wRate,
135 int bNeedAck, u8 byFBOption);
Forest Bond92b96792009-06-13 07:38:31 -0400136
Malcolm Priestleyaceaf012013-11-26 19:06:35 +0000137static struct vnt_usb_send_context
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000138 *s_vGetFreeContext(struct vnt_private *priv)
Forest Bond92b96792009-06-13 07:38:31 -0400139{
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000140 struct vnt_usb_send_context *context = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000141 int ii;
Forest Bond92b96792009-06-13 07:38:31 -0400142
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000143 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n");
Forest Bond92b96792009-06-13 07:38:31 -0400144
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000145 for (ii = 0; ii < priv->cbTD; ii++) {
146 if (!priv->apTD[ii])
147 return NULL;
148
149 context = priv->apTD[ii];
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100150 if (context->in_use == false) {
151 context->in_use = true;
152 memset(context->data, 0,
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000153 MAX_TOTAL_SIZE_WITH_ALL_HEADERS);
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100154
155 context->hdr = NULL;
156
Malcolm Priestleyb89f3b92013-11-26 19:16:59 +0000157 return context;
158 }
159 }
160
161 if (ii == priv->cbTD)
162 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n");
Malcolm Priestleyaceaf012013-11-26 19:06:35 +0000163
Malcolm Priestley5c851382013-11-26 19:12:38 +0000164 return NULL;
Forest Bond92b96792009-06-13 07:38:31 -0400165}
166
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000167static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
168 u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl)
Forest Bond92b96792009-06-13 07:38:31 -0400169{
Malcolm Priestleyae27b142013-12-09 22:23:19 +0000170 struct net_device_stats *stats = &pDevice->stats;
Malcolm Priestley51934e72013-12-09 22:30:14 +0000171 struct vnt_tx_pkt_info *pkt_info = pDevice->pkt_info;
Forest Bond92b96792009-06-13 07:38:31 -0400172
Malcolm Priestley51934e72013-12-09 22:30:14 +0000173 pkt_info[byPktNum].fifo_ctl = wFIFOCtl;
174 memcpy(pkt_info[byPktNum].dest_addr, pbyDestAddr, ETH_ALEN);
Malcolm Priestleyae27b142013-12-09 22:23:19 +0000175
176 stats->tx_bytes += wPktLength;
Forest Bond92b96792009-06-13 07:38:31 -0400177}
178
Malcolm Priestley3695c462014-05-31 13:34:59 +0100179static void s_vFillTxKey(struct vnt_usb_send_context *tx_context,
Malcolm Priestley3ba09382013-10-15 21:41:38 +0100180 struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead,
Malcolm Priestley3695c462014-05-31 13:34:59 +0100181 PSKeyItem pTransmitKey, u16 wPayloadLen, struct vnt_mic_hdr *mic_hdr)
Forest Bond92b96792009-06-13 07:38:31 -0400182{
Malcolm Priestley3695c462014-05-31 13:34:59 +0100183 struct vnt_private *pDevice = tx_context->priv;
184 struct ieee80211_hdr *pMACHeader = tx_context->hdr;
Malcolm Priestleyab51f512014-05-31 13:35:00 +0100185 u8 *pbyBuf = fifo_head->tx_key;
Malcolm Priestleyfb453db2014-03-22 09:01:24 +0000186 __le32 *pdwIV = (__le32 *)pbyIVHead;
Malcolm Priestley2fbb2302014-03-22 09:01:25 +0000187 __le32 *pdwExtIV = (__le32 *)((u8 *)pbyIVHead + 4);
Malcolm Priestleyfbfaccf2014-03-22 09:01:23 +0000188 __le32 rev_iv_counter;
Forest Bond92b96792009-06-13 07:38:31 -0400189
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100190 /* Fill TXKEY */
191 if (pTransmitKey == NULL)
Malcolm Priestleyec37d8b2013-08-23 14:37:48 +0100192 return;
Forest Bond92b96792009-06-13 07:38:31 -0400193
Malcolm Priestleyfbfaccf2014-03-22 09:01:23 +0000194 rev_iv_counter = cpu_to_le32(pDevice->dwIVCounter);
Malcolm Priestleyfb453db2014-03-22 09:01:24 +0000195 *pdwIV = cpu_to_le32(pDevice->dwIVCounter);
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100196 pDevice->byKeyIndex = pTransmitKey->dwKeyIndex & 0xf;
Forest Bond92b96792009-06-13 07:38:31 -0400197
Malcolm Priestleyf6804f32013-08-27 12:32:01 +0100198 switch (pTransmitKey->byCipherSuite) {
199 case KEY_CTL_WEP:
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100200 if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) {
Malcolm Priestleyfbfaccf2014-03-22 09:01:23 +0000201 memcpy(pDevice->abyPRNG, (u8 *)&rev_iv_counter, 3);
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100202 memcpy(pDevice->abyPRNG + 3, pTransmitKey->abyKey,
203 pTransmitKey->uKeyLength);
204 } else {
Malcolm Priestleyfbfaccf2014-03-22 09:01:23 +0000205 memcpy(pbyBuf, (u8 *)&rev_iv_counter, 3);
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100206 memcpy(pbyBuf + 3, pTransmitKey->abyKey,
207 pTransmitKey->uKeyLength);
208 if (pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) {
Malcolm Priestleyfbfaccf2014-03-22 09:01:23 +0000209 memcpy(pbyBuf+8, (u8 *)&rev_iv_counter, 3);
Malcolm Priestley5cb5bff72014-05-25 21:36:28 +0100210 memcpy(pbyBuf+11, pTransmitKey->abyKey,
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100211 pTransmitKey->uKeyLength);
212 }
Malcolm Priestleyec37d8b2013-08-23 14:37:48 +0100213
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100214 memcpy(pDevice->abyPRNG, pbyBuf, 16);
215 }
216 /* Append IV after Mac Header */
Malcolm Priestleyfb453db2014-03-22 09:01:24 +0000217 *pdwIV &= cpu_to_le32(WEP_IV_MASK);
218 *pdwIV |= cpu_to_le32((u32)pDevice->byKeyIndex << 30);
Malcolm Priestleyec37d8b2013-08-23 14:37:48 +0100219
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100220 pDevice->dwIVCounter++;
221 if (pDevice->dwIVCounter > WEP_IV_MASK)
222 pDevice->dwIVCounter = 0;
Malcolm Priestleyf6804f32013-08-27 12:32:01 +0100223
224 break;
225 case KEY_CTL_TKIP:
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100226 pTransmitKey->wTSC15_0++;
227 if (pTransmitKey->wTSC15_0 == 0)
228 pTransmitKey->dwTSC47_16++;
Malcolm Priestleyec37d8b2013-08-23 14:37:48 +0100229
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100230 TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
231 pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16,
232 pDevice->abyPRNG);
233 memcpy(pbyBuf, pDevice->abyPRNG, 16);
234
235 /* Make IV */
236 memcpy(pdwIV, pDevice->abyPRNG, 3);
237
238 *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) &
239 0xc0) | 0x20);
240 /* Append IV&ExtIV after Mac Header */
241 *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
242
243 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
244 "vFillTxKey()---- pdwExtIV: %x\n", *pdwExtIV);
245
Malcolm Priestleyf6804f32013-08-27 12:32:01 +0100246 break;
247 case KEY_CTL_CCMP:
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100248 pTransmitKey->wTSC15_0++;
249 if (pTransmitKey->wTSC15_0 == 0)
250 pTransmitKey->dwTSC47_16++;
251
252 memcpy(pbyBuf, pTransmitKey->abyKey, 16);
253
254 /* Make IV */
255 *pdwIV = 0;
256 *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) &
257 0xc0) | 0x20);
258
Malcolm Priestleyfb453db2014-03-22 09:01:24 +0000259 *pdwIV |= cpu_to_le32((u32)(pTransmitKey->wTSC15_0));
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100260
261 /* Append IV&ExtIV after Mac Header */
262 *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
263
264 if (!mic_hdr)
265 return;
266
267 /* MICHDR0 */
268 mic_hdr->id = 0x59;
269 mic_hdr->payload_len = cpu_to_be16(wPayloadLen);
270 memcpy(mic_hdr->mic_addr2, pMACHeader->addr2, ETH_ALEN);
271
272 mic_hdr->tsc_47_16 = cpu_to_be32(pTransmitKey->dwTSC47_16);
273 mic_hdr->tsc_15_0 = cpu_to_be16(pTransmitKey->wTSC15_0);
274
275 /* MICHDR1 */
Malcolm Priestley078d0cf2013-11-25 22:14:16 +0000276 if (ieee80211_has_a4(pMACHeader->frame_control))
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100277 mic_hdr->hlen = cpu_to_be16(28);
278 else
279 mic_hdr->hlen = cpu_to_be16(22);
280
281 memcpy(mic_hdr->addr1, pMACHeader->addr1, ETH_ALEN);
282 memcpy(mic_hdr->addr2, pMACHeader->addr2, ETH_ALEN);
283
284 /* MICHDR2 */
285 memcpy(mic_hdr->addr3, pMACHeader->addr3, ETH_ALEN);
Malcolm Priestley5d4fe752014-03-22 09:01:26 +0000286 mic_hdr->frame_control = cpu_to_le16(
287 le16_to_cpu(pMACHeader->frame_control) & 0xc78f);
288 mic_hdr->seq_ctrl = cpu_to_le16(
289 le16_to_cpu(pMACHeader->seq_ctrl) & 0xf);
Malcolm Priestleyec37d8b2013-08-23 14:37:48 +0100290
Malcolm Priestley078d0cf2013-11-25 22:14:16 +0000291 if (ieee80211_has_a4(pMACHeader->frame_control))
Malcolm Priestley95bfb1a2013-08-27 12:29:10 +0100292 memcpy(mic_hdr->addr4, pMACHeader->addr4, ETH_ALEN);
293 }
Forest Bond92b96792009-06-13 07:38:31 -0400294}
295
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000296static void s_vSWencryption(struct vnt_private *pDevice,
297 PSKeyItem pTransmitKey, u8 *pbyPayloadHead, u16 wPayloadSize)
Forest Bond92b96792009-06-13 07:38:31 -0400298{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000299 u32 cbICVlen = 4;
300 u32 dwICV = 0xffffffff;
301 u32 *pdwICV;
Forest Bond92b96792009-06-13 07:38:31 -0400302
303 if (pTransmitKey == NULL)
304 return;
305
306 if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
307 //=======================================================================
308 // Append ICV after payload
Malcolm Priestley929cb312014-05-21 21:09:42 +0100309 dwICV = ether_crc_le(wPayloadSize, pbyPayloadHead);
Andres More52a7e642013-02-25 20:32:53 -0500310 pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize);
Forest Bond92b96792009-06-13 07:38:31 -0400311 // finally, we must invert dwCRC to get the correct answer
312 *pdwICV = cpu_to_le32(~dwICV);
313 // RC4 encryption
314 rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3);
315 rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
316 //=======================================================================
317 } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
318 //=======================================================================
319 //Append ICV after payload
Malcolm Priestley929cb312014-05-21 21:09:42 +0100320 dwICV = ether_crc_le(wPayloadSize, pbyPayloadHead);
Andres More52a7e642013-02-25 20:32:53 -0500321 pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize);
Forest Bond92b96792009-06-13 07:38:31 -0400322 // finally, we must invert dwCRC to get the correct answer
323 *pdwICV = cpu_to_le32(~dwICV);
324 // RC4 encryption
325 rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
326 rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
327 //=======================================================================
328 }
329}
330
Malcolm Priestleydab085b2014-03-18 19:25:03 +0000331static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
Malcolm Priestleyf115e762013-08-23 11:48:46 +0100332{
333 return cpu_to_le16(wTimeStampOff[priv->byPreambleType % 2]
334 [rate % MAX_RATE]);
335}
336
Forest Bond92b96792009-06-13 07:38:31 -0400337/*byPktType : PK_TYPE_11A 0
338 PK_TYPE_11B 1
339 PK_TYPE_11GB 2
340 PK_TYPE_11GA 3
341*/
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000342static u32 s_uGetTxRsvTime(struct vnt_private *priv, u8 pkt_type,
343 u32 frame_length, u16 rate, int need_ack)
Forest Bond92b96792009-06-13 07:38:31 -0400344{
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000345 u32 data_time, ack_time;
Forest Bond92b96792009-06-13 07:38:31 -0400346
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100347 data_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000348 frame_length, rate);
Forest Bond92b96792009-06-13 07:38:31 -0400349
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000350 if (pkt_type == PK_TYPE_11B)
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100351 ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
352 14, (u16)priv->byTopCCKBasicRate);
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000353 else
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100354 ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
355 14, (u16)priv->byTopOFDMBasicRate);
Malcolm Priestley3fd56202014-01-08 20:08:42 +0000356
357 if (need_ack)
358 return data_time + priv->uSIFS + ack_time;
359
360 return data_time;
Forest Bond92b96792009-06-13 07:38:31 -0400361}
362
Malcolm Priestley2075f652014-03-18 19:25:07 +0000363static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
Malcolm Priestley9c3806d2013-08-23 11:32:26 +0100364 u32 frame_length, u16 rate, int need_ack)
365{
366 return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type,
367 frame_length, rate, need_ack));
368}
369
Forest Bond92b96792009-06-13 07:38:31 -0400370//byFreqType: 0=>5GHZ 1=>2.4GHZ
Malcolm Priestley20338012014-03-18 19:25:08 +0000371static __le16 s_uGetRTSCTSRsvTime(struct vnt_private *priv,
Malcolm Priestley3b6cee7be2014-05-25 21:36:27 +0100372 u8 rsv_type, u8 pkt_type, u32 frame_length, u16 current_rate)
Forest Bond92b96792009-06-13 07:38:31 -0400373{
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000374 u32 rrv_time, rts_time, cts_time, ack_time, data_time;
Forest Bond92b96792009-06-13 07:38:31 -0400375
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000376 rrv_time = rts_time = cts_time = ack_time = data_time = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400377
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100378 data_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley3b6cee7be2014-05-25 21:36:27 +0100379 frame_length, current_rate);
Forest Bond92b96792009-06-13 07:38:31 -0400380
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000381 if (rsv_type == 0) {
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100382 rts_time = vnt_get_frame_time(priv->byPreambleType,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000383 pkt_type, 20, priv->byTopCCKBasicRate);
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100384 cts_time = ack_time = vnt_get_frame_time(priv->byPreambleType,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000385 pkt_type, 14, priv->byTopCCKBasicRate);
386 } else if (rsv_type == 1) {
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100387 rts_time = vnt_get_frame_time(priv->byPreambleType,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000388 pkt_type, 20, priv->byTopCCKBasicRate);
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100389 cts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000390 14, priv->byTopCCKBasicRate);
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100391 ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000392 14, priv->byTopOFDMBasicRate);
393 } else if (rsv_type == 2) {
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100394 rts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000395 20, priv->byTopOFDMBasicRate);
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100396 cts_time = ack_time = vnt_get_frame_time(priv->byPreambleType,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000397 pkt_type, 14, priv->byTopOFDMBasicRate);
398 } else if (rsv_type == 3) {
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100399 cts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000400 14, priv->byTopCCKBasicRate);
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100401 ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type,
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000402 14, priv->byTopOFDMBasicRate);
403
404 rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS;
405
Malcolm Priestley20338012014-03-18 19:25:08 +0000406 return cpu_to_le16((u16)rrv_time);
Malcolm Priestley342e2e22014-01-08 20:13:29 +0000407 }
408
409 rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS;
410
411 return cpu_to_le16((u16)rrv_time);
Forest Bond92b96792009-06-13 07:38:31 -0400412}
413
414//byFreqType 0: 5GHz, 1:2.4Ghz
Malcolm Priestley5abe3d62014-03-18 19:25:06 +0000415static __le16 s_uGetDataDuration(struct vnt_private *pDevice,
Malcolm Priestley6b5ad9d2013-08-21 22:16:04 +0100416 u8 byPktType, int bNeedAck)
Forest Bond92b96792009-06-13 07:38:31 -0400417{
Malcolm Priestley0005cb02013-08-07 21:26:12 +0100418 u32 uAckTime = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400419
Malcolm Priestleyb02ccd52013-08-13 19:59:31 +0100420 if (bNeedAck) {
Malcolm Priestley6b5ad9d2013-08-21 22:16:04 +0100421 if (byPktType == PK_TYPE_11B)
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100422 uAckTime = vnt_get_frame_time(pDevice->byPreambleType,
Malcolm Priestleyb02ccd52013-08-13 19:59:31 +0100423 byPktType, 14, pDevice->byTopCCKBasicRate);
424 else
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100425 uAckTime = vnt_get_frame_time(pDevice->byPreambleType,
Malcolm Priestleyb02ccd52013-08-13 19:59:31 +0100426 byPktType, 14, pDevice->byTopOFDMBasicRate);
Malcolm Priestleyd5005952013-08-21 21:58:37 +0100427 return cpu_to_le16((u16)(pDevice->uSIFS + uAckTime));
Malcolm Priestleyb02ccd52013-08-13 19:59:31 +0100428 }
Forest Bond92b96792009-06-13 07:38:31 -0400429
Forest Bond92b96792009-06-13 07:38:31 -0400430 return 0;
431}
432
Forest Bond92b96792009-06-13 07:38:31 -0400433//byFreqType: 0=>5GHZ 1=>2.4GHZ
Malcolm Priestley7f591a12014-03-18 19:25:05 +0000434static __le16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType,
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000435 u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck,
436 u8 byFBOption)
Forest Bond92b96792009-06-13 07:38:31 -0400437{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000438 u32 uCTSTime = 0, uDurTime = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400439
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100440 switch (byDurType) {
441 case RTSDUR_BB:
442 case RTSDUR_BA:
443 case RTSDUR_BA_F0:
444 case RTSDUR_BA_F1:
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100445 uCTSTime = vnt_get_frame_time(pDevice->byPreambleType,
446 byPktType, 14, pDevice->byTopCCKBasicRate);
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100447 uDurTime = uCTSTime + 2 * pDevice->uSIFS +
448 s_uGetTxRsvTime(pDevice, byPktType,
449 cbFrameLength, wRate, bNeedAck);
450 break;
Forest Bond92b96792009-06-13 07:38:31 -0400451
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100452 case RTSDUR_AA:
453 case RTSDUR_AA_F0:
454 case RTSDUR_AA_F1:
Malcolm Priestleyd38ee5b2014-06-04 18:25:35 +0100455 uCTSTime = vnt_get_frame_time(pDevice->byPreambleType,
456 byPktType, 14, pDevice->byTopOFDMBasicRate);
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100457 uDurTime = uCTSTime + 2 * pDevice->uSIFS +
458 s_uGetTxRsvTime(pDevice, byPktType,
459 cbFrameLength, wRate, bNeedAck);
460 break;
Forest Bond92b96792009-06-13 07:38:31 -0400461
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100462 case CTSDUR_BA:
463 case CTSDUR_BA_F0:
464 case CTSDUR_BA_F1:
465 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100466 byPktType, cbFrameLength, wRate, bNeedAck);
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100467 break;
Forest Bond92b96792009-06-13 07:38:31 -0400468
Malcolm Priestleyecd80242013-10-15 21:05:02 +0100469 default:
470 break;
471 }
Forest Bond92b96792009-06-13 07:38:31 -0400472
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100473 return cpu_to_le16((u16)uDurTime);
Forest Bond92b96792009-06-13 07:38:31 -0400474}
475
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100476static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context,
477 struct ieee80211_hdr *hdr)
478{
479 u8 *head = tx_context->data + offsetof(struct vnt_tx_buffer, fifo_head);
480 u8 *hdr_pos = (u8 *)hdr;
481
482 tx_context->hdr = hdr;
483 if (!tx_context->hdr)
484 return 0;
485
486 return (u16)(hdr_pos - head);
487}
488
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100489static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
490 u8 pkt_type, u16 rate, struct vnt_tx_datahead_g *buf,
491 u32 frame_len, int need_ack)
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100492{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100493
494 struct vnt_private *priv = tx_context->priv;
495
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100496 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100497 vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a);
498 vnt_get_phy_field(priv, frame_len, priv->byTopCCKBasicRate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100499 PK_TYPE_11B, &buf->b);
500
501 /* Get Duration and TimeStamp */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000502 buf->duration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
503 buf->duration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100504
Malcolm Priestley10bb39a2014-03-18 19:25:01 +0000505 buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
506 buf->time_stamp_off_b = vnt_time_stamp_off(priv,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100507 priv->byTopCCKBasicRate);
508
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100509 tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
510
Malcolm Priestleyc4cf6df2014-03-18 19:25:04 +0000511 return le16_to_cpu(buf->duration_a);
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100512}
513
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100514static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context,
515 u8 pkt_type, u16 rate, struct vnt_tx_datahead_g_fb *buf,
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100516 u32 frame_len, int need_ack)
517{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100518 struct vnt_private *priv = tx_context->priv;
519
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100520 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100521 vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100522
Malcolm Priestley205056f2014-06-04 18:25:34 +0100523 vnt_get_phy_field(priv, frame_len, priv->byTopCCKBasicRate,
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100524 PK_TYPE_11B, &buf->b);
525
526 /* Get Duration and TimeStamp */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000527 buf->duration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
528 buf->duration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100529
Malcolm Priestley4e011172014-03-18 19:24:55 +0000530 buf->duration_a_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
531 buf->duration_a_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100532
Malcolm Priestley10bb39a2014-03-18 19:25:01 +0000533 buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
534 buf->time_stamp_off_b = vnt_time_stamp_off(priv,
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100535 priv->byTopCCKBasicRate);
536
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100537 tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
538
Malcolm Priestleyc4cf6df2014-03-18 19:25:04 +0000539 return le16_to_cpu(buf->duration_a);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100540}
541
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100542static u16 vnt_rxtx_datahead_a_fb(struct vnt_usb_send_context *tx_context,
543 u8 pkt_type, u16 rate, struct vnt_tx_datahead_a_fb *buf,
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100544 u32 frame_len, int need_ack)
545{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100546 struct vnt_private *priv = tx_context->priv;
547
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100548 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100549 vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a);
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100550 /* Get Duration and TimeStampOff */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000551 buf->duration = s_uGetDataDuration(priv, pkt_type, need_ack);
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100552
Malcolm Priestley4e011172014-03-18 19:24:55 +0000553 buf->duration_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
554 buf->duration_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100555
Malcolm Priestley10bb39a2014-03-18 19:25:01 +0000556 buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100557
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100558 tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
559
Malcolm Priestleyc4cf6df2014-03-18 19:25:04 +0000560 return le16_to_cpu(buf->duration);
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100561}
562
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100563static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context,
564 u8 pkt_type, u16 rate, struct vnt_tx_datahead_ab *buf,
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100565 u32 frame_len, int need_ack)
566{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100567 struct vnt_private *priv = tx_context->priv;
568
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100569 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100570 vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->ab);
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100571 /* Get Duration and TimeStampOff */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000572 buf->duration = s_uGetDataDuration(priv, pkt_type, need_ack);
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100573
Malcolm Priestley10bb39a2014-03-18 19:25:01 +0000574 buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100575
Malcolm Priestley1622c8f2014-05-31 13:34:58 +0100576 tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
577
Malcolm Priestleyc4cf6df2014-03-18 19:25:04 +0000578 return le16_to_cpu(buf->duration);
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100579}
580
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100581static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context,
582 struct ieee80211_rts *rts, __le16 duration)
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100583{
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100584 struct ieee80211_hdr *hdr =
585 (struct ieee80211_hdr *)tx_context->skb->data;
586
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100587 rts->duration = duration;
Malcolm Priestleyf4554d32014-03-22 09:01:31 +0000588 rts->frame_control =
589 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100590
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100591 memcpy(rts->ra, hdr->addr1, ETH_ALEN);
592 memcpy(rts->ta, hdr->addr2, ETH_ALEN);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100593
594 return 0;
595}
596
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100597static u16 vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100598 struct vnt_rts_g *buf, struct ethhdr *eth_hdr,
599 u8 pkt_type, u32 frame_len, int need_ack,
600 u16 current_rate, u8 fb_option)
601{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100602 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100603 u16 rts_frame_len = 20;
604
Malcolm Priestley205056f2014-06-04 18:25:34 +0100605 vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100606 PK_TYPE_11B, &buf->b);
Malcolm Priestley205056f2014-06-04 18:25:34 +0100607 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100608 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
609
Malcolm Priestley4e011172014-03-18 19:24:55 +0000610 buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100611 PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000612 buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100613 pkt_type, current_rate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000614 buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100615 pkt_type, current_rate, need_ack, fb_option);
616
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100617 vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100618
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100619 return vnt_rxtx_datahead_g(tx_context, pkt_type, current_rate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100620 &buf->data_head, frame_len, need_ack);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100621}
622
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100623static u16 vnt_rxtx_rts_g_fb_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100624 struct vnt_rts_g_fb *buf, struct ethhdr *eth_hdr,
625 u8 pkt_type, u32 frame_len, int need_ack,
626 u16 current_rate, u8 fb_option)
627{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100628 struct vnt_private *priv = tx_context->priv;
Malcolm Priestleyec917132013-08-26 11:07:46 +0100629 u16 rts_frame_len = 20;
630
Malcolm Priestley205056f2014-06-04 18:25:34 +0100631 vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100632 PK_TYPE_11B, &buf->b);
Malcolm Priestley205056f2014-06-04 18:25:34 +0100633 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100634 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
635
636
Malcolm Priestley4e011172014-03-18 19:24:55 +0000637 buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100638 PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000639 buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100640 pkt_type, current_rate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000641 buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100642 pkt_type, current_rate, need_ack, fb_option);
643
644
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000645 buf->rts_duration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100646 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000647 buf->rts_duration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100648 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000649 buf->rts_duration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100650 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000651 buf->rts_duration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100652 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100653
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100654 vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100655
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100656 return vnt_rxtx_datahead_g_fb(tx_context, pkt_type, current_rate,
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100657 &buf->data_head, frame_len, need_ack);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100658}
659
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100660static u16 vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley17126332013-08-26 11:09:38 +0100661 struct vnt_rts_ab *buf, struct ethhdr *eth_hdr,
662 u8 pkt_type, u32 frame_len, int need_ack,
663 u16 current_rate, u8 fb_option)
664{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100665 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley17126332013-08-26 11:09:38 +0100666 u16 rts_frame_len = 20;
667
Malcolm Priestley205056f2014-06-04 18:25:34 +0100668 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley17126332013-08-26 11:09:38 +0100669 priv->byTopOFDMBasicRate, pkt_type, &buf->ab);
670
Malcolm Priestley4e011172014-03-18 19:24:55 +0000671 buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley17126332013-08-26 11:09:38 +0100672 pkt_type, current_rate, need_ack, fb_option);
673
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100674 vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
Malcolm Priestley17126332013-08-26 11:09:38 +0100675
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100676 return vnt_rxtx_datahead_ab(tx_context, pkt_type, current_rate,
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100677 &buf->data_head, frame_len, need_ack);
Malcolm Priestley17126332013-08-26 11:09:38 +0100678}
679
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100680static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100681 struct vnt_rts_a_fb *buf, struct ethhdr *eth_hdr,
682 u8 pkt_type, u32 frame_len, int need_ack,
683 u16 current_rate, u8 fb_option)
684{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100685 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100686 u16 rts_frame_len = 20;
687
Malcolm Priestley205056f2014-06-04 18:25:34 +0100688 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100689 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
690
Malcolm Priestley4e011172014-03-18 19:24:55 +0000691 buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100692 pkt_type, current_rate, need_ack, fb_option);
693
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000694 buf->rts_duration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100695 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100696
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000697 buf->rts_duration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100698 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100699
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100700 vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100701
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100702 return vnt_rxtx_datahead_a_fb(tx_context, pkt_type, current_rate,
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100703 &buf->data_head, frame_len, need_ack);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100704}
705
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100706static u16 s_vFillRTSHead(struct vnt_usb_send_context *tx_context, u8 byPktType,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100707 union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
Andres Moreceb8c5d2013-03-18 20:33:49 -0500708 struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
Forest Bond92b96792009-06-13 07:38:31 -0400709{
Forest Bond92b96792009-06-13 07:38:31 -0400710
Malcolm Priestley13fe62a2013-08-26 11:17:52 +0100711 if (!head)
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100712 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400713
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100714 /* Note: So far RTSHead doesn't appear in ATIM
715 * & Beacom DMA, so we don't need to take them
716 * into account.
717 * Otherwise, we need to modified codes for them.
718 */
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100719 switch (byPktType) {
720 case PK_TYPE_11GB:
721 case PK_TYPE_11GA:
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100722 if (byFBOption == AUTO_FB_NONE)
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100723 return vnt_rxtx_rts_g_head(tx_context, &head->rts_g,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100724 psEthHeader, byPktType, cbFrameLength,
725 bNeedAck, wCurrentRate, byFBOption);
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100726 else
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100727 return vnt_rxtx_rts_g_fb_head(tx_context,
728 &head->rts_g_fb, psEthHeader, byPktType,
729 cbFrameLength, bNeedAck, wCurrentRate,
730 byFBOption);
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100731 break;
732 case PK_TYPE_11A:
Malcolm Priestley2b83ebd2013-08-27 09:58:21 +0100733 if (byFBOption) {
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100734 return vnt_rxtx_rts_a_fb_head(tx_context,
735 &head->rts_a_fb, psEthHeader, byPktType,
736 cbFrameLength, bNeedAck, wCurrentRate,
737 byFBOption);
Malcolm Priestley2b83ebd2013-08-27 09:58:21 +0100738 break;
739 }
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100740 case PK_TYPE_11B:
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100741 return vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab,
Malcolm Priestley17126332013-08-26 11:09:38 +0100742 psEthHeader, byPktType, cbFrameLength,
743 bNeedAck, wCurrentRate, byFBOption);
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100744 }
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100745
746 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400747}
748
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100749static u16 s_vFillCTSHead(struct vnt_usb_send_context *tx_context,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100750 u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
751 int bNeedAck, u16 wCurrentRate, u8 byFBOption)
Forest Bond92b96792009-06-13 07:38:31 -0400752{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100753 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000754 u32 uCTSFrameLen = 14;
Forest Bond92b96792009-06-13 07:38:31 -0400755
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100756 if (!head)
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100757 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400758
Malcolm Priestleyc921cc82013-08-20 20:47:49 +0100759 if (byFBOption != AUTO_FB_NONE) {
760 /* Auto Fall back */
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100761 struct vnt_cts_fb *pBuf = &head->cts_g_fb;
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100762 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100763 vnt_get_phy_field(pDevice, uCTSFrameLen,
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100764 pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000765 pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100766 cbFrameLength, byPktType,
767 wCurrentRate, bNeedAck, byFBOption);
768 /* Get CTSDuration_ba_f0 */
Malcolm Priestley7fd57472014-03-18 19:24:59 +0000769 pBuf->cts_duration_ba_f0 = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100770 CTSDUR_BA_F0, cbFrameLength, byPktType,
771 pDevice->tx_rate_fb0, bNeedAck, byFBOption);
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100772 /* Get CTSDuration_ba_f1 */
Malcolm Priestley7fd57472014-03-18 19:24:59 +0000773 pBuf->cts_duration_ba_f1 = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100774 CTSDUR_BA_F1, cbFrameLength, byPktType,
775 pDevice->tx_rate_fb1, bNeedAck, byFBOption);
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100776 /* Get CTS Frame body */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000777 pBuf->data.duration = pBuf->duration_ba;
Malcolm Priestleyd9560ae2014-03-22 09:01:32 +0000778 pBuf->data.frame_control =
779 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
780
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100781 memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100782
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100783 return vnt_rxtx_datahead_g_fb(tx_context, byPktType,
784 wCurrentRate, &pBuf->data_head, cbFrameLength,
785 bNeedAck);
Malcolm Priestleyc921cc82013-08-20 20:47:49 +0100786 } else {
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100787 struct vnt_cts *pBuf = &head->cts_g;
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100788 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100789 vnt_get_phy_field(pDevice, uCTSFrameLen,
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100790 pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100791 /* Get CTSDuration_ba */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000792 pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100793 CTSDUR_BA, cbFrameLength, byPktType,
794 wCurrentRate, bNeedAck, byFBOption);
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100795 /*Get CTS Frame body*/
Malcolm Priestley4e011172014-03-18 19:24:55 +0000796 pBuf->data.duration = pBuf->duration_ba;
Malcolm Priestleyd9560ae2014-03-22 09:01:32 +0000797 pBuf->data.frame_control =
798 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
799
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100800 memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100801
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100802 return vnt_rxtx_datahead_g(tx_context, byPktType, wCurrentRate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100803 &pBuf->data_head, cbFrameLength, bNeedAck);
Forest Bond92b96792009-06-13 07:38:31 -0400804 }
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100805
806 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400807}
808
Forest Bond92b96792009-06-13 07:38:31 -0400809/*+
810 *
811 * Description:
812 * Generate FIFO control for MAC & Baseband controller
813 *
814 * Parameters:
815 * In:
816 * pDevice - Pointer to adpater
817 * pTxDataHead - Transmit Data Buffer
818 * pTxBufHead - pTxBufHead
819 * pvRrvTime - pvRrvTime
820 * pvRTS - RTS Buffer
821 * pCTS - CTS Buffer
822 * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS)
823 * bNeedACK - If need ACK
Forest Bond92b96792009-06-13 07:38:31 -0400824 * Out:
825 * none
826 *
827 * Return Value: none
828 *
829-*/
Andres Morecc856e62010-05-17 21:34:01 -0300830
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100831static u16 s_vGenerateTxParameter(struct vnt_usb_send_context *tx_context,
Malcolm Priestley8e344c82013-09-17 19:58:11 +0100832 u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
Malcolm Priestleyfa575602013-09-26 19:00:41 +0100833 struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
Malcolm Priestley05cc6172014-04-30 21:31:12 +0100834 int bNeedACK, struct ethhdr *psEthHeader, bool need_rts)
Forest Bond92b96792009-06-13 07:38:31 -0400835{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100836 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestley8e344c82013-09-17 19:58:11 +0100837 struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100838 union vnt_tx_data_head *head = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000839 u16 wFifoCtl;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000840 u8 byFBOption = AUTO_FB_NONE;
Forest Bond92b96792009-06-13 07:38:31 -0400841
Malcolm Priestley03a9cf32014-03-22 09:01:30 +0000842 pFifoHead->current_rate = cpu_to_le16(wCurrentRate);
Malcolm Priestley92928f12013-10-07 20:14:01 +0100843 wFifoCtl = pFifoHead->wFIFOCtl;
Forest Bond92b96792009-06-13 07:38:31 -0400844
Malcolm Priestley92928f12013-10-07 20:14:01 +0100845 if (wFifoCtl & FIFOCTL_AUTO_FB_0)
846 byFBOption = AUTO_FB_0;
847 else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
848 byFBOption = AUTO_FB_1;
Forest Bond92b96792009-06-13 07:38:31 -0400849
Malcolm Priestley92928f12013-10-07 20:14:01 +0100850 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
851 if (need_rts) {
852 struct vnt_rrv_time_rts *pBuf =
853 &tx_buffer->tx_head.tx_rts.rts;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100854
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000855 pBuf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100856 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000857 pBuf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 1,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100858 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000859 pBuf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(pDevice, 0,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100860 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100861
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000862 pBuf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100863 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000864 pBuf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100865 PK_TYPE_11B, cbFrameSize,
866 pDevice->byTopCCKBasicRate, bNeedACK);
867
868 if (need_mic) {
869 *mic_hdr = &tx_buffer->
870 tx_head.tx_rts.tx.mic.hdr;
871 head = &tx_buffer->tx_head.tx_rts.tx.mic.head;
872 } else {
873 head = &tx_buffer->tx_head.tx_rts.tx.head;
874 }
875
876 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100877 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100878 cbFrameSize, bNeedACK, psEthHeader,
879 wCurrentRate, byFBOption);
880
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100881 } else {
Malcolm Priestley92928f12013-10-07 20:14:01 +0100882 struct vnt_rrv_time_cts *pBuf = &tx_buffer->
883 tx_head.tx_cts.cts;
884
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000885 pBuf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100886 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000887 pBuf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100888 PK_TYPE_11B, cbFrameSize,
889 pDevice->byTopCCKBasicRate, bNeedACK);
890
Malcolm Priestley372108e2014-03-18 19:25:00 +0000891 pBuf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100892 byPktType, cbFrameSize, wCurrentRate);
893
894 if (need_mic) {
895 *mic_hdr = &tx_buffer->
896 tx_head.tx_cts.tx.mic.hdr;
897 head = &tx_buffer->tx_head.tx_cts.tx.mic.head;
898 } else {
899 head = &tx_buffer->tx_head.tx_cts.tx.head;
900 }
901
902 /* Fill CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100903 return s_vFillCTSHead(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100904 head, cbFrameSize, bNeedACK, wCurrentRate,
905 byFBOption);
906 }
907 } else if (byPktType == PK_TYPE_11A) {
908 if (need_mic) {
909 *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
910 head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
911 } else {
912 head = &tx_buffer->tx_head.tx_ab.tx.head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100913 }
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100914
Malcolm Priestley92928f12013-10-07 20:14:01 +0100915 if (need_rts) {
916 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
917 tx_head.tx_ab.ab;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100918
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000919 pBuf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100920 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100921
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000922 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100923 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
924
925 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100926 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100927 cbFrameSize, bNeedACK, psEthHeader,
928 wCurrentRate, byFBOption);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100929 } else {
Malcolm Priestley92928f12013-10-07 20:14:01 +0100930 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
931 tx_head.tx_ab.ab;
932
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000933 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100934 PK_TYPE_11A, cbFrameSize,
935 wCurrentRate, bNeedACK);
936
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100937 return vnt_rxtx_datahead_a_fb(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100938 wCurrentRate, &head->data_head_a_fb,
939 cbFrameSize, bNeedACK);
940 }
941 } else if (byPktType == PK_TYPE_11B) {
942 if (need_mic) {
943 *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
944 head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
945 } else {
946 head = &tx_buffer->tx_head.tx_ab.tx.head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100947 }
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100948
Malcolm Priestley92928f12013-10-07 20:14:01 +0100949 if (need_rts) {
950 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
951 tx_head.tx_ab.ab;
Malcolm Priestleya90186e2013-10-01 15:58:54 +0100952
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000953 pBuf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100954 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100955
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000956 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100957 PK_TYPE_11B, cbFrameSize, wCurrentRate,
958 bNeedACK);
959
960 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100961 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100962 cbFrameSize,
Malcolm Priestley351c7dc2013-08-27 12:02:54 +0100963 bNeedACK, psEthHeader, wCurrentRate, byFBOption);
Malcolm Priestley92928f12013-10-07 20:14:01 +0100964 } else {
965 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
966 tx_head.tx_ab.ab;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100967
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000968 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100969 PK_TYPE_11B, cbFrameSize,
970 wCurrentRate, bNeedACK);
Malcolm Priestleya90186e2013-10-01 15:58:54 +0100971
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100972 return vnt_rxtx_datahead_ab(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100973 wCurrentRate, &head->data_head_ab,
974 cbFrameSize, bNeedACK);
975 }
Malcolm Priestleyc12dca02013-10-01 16:03:40 +0100976 }
977
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100978 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400979}
980/*
Andres Moreb902fbf2013-02-25 20:32:51 -0500981 u8 * pbyBuffer,//point to pTxBufHead
Andres More3eaca0d2013-02-25 20:32:52 -0500982 u16 wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
Andres Morecc856e62010-05-17 21:34:01 -0300983 unsigned int cbFragmentSize,//Hdr+payoad+FCS
Forest Bond92b96792009-06-13 07:38:31 -0400984*/
985
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100986static int s_bPacketToWirelessUsb(struct vnt_usb_send_context *tx_context,
987 u8 byPktType, struct vnt_tx_buffer *tx_buffer, int bNeedEncryption,
Malcolm Priestley05cc6172014-04-30 21:31:12 +0100988 u32 uSkbPacketLen, struct ethhdr *psEthHeader,
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +0100989 u8 *pPacket, PSKeyItem pTransmitKey, u32 uNodeIndex, u16 wCurrentRate,
990 u32 *pcbHeaderLen, u32 *pcbTotalLen)
Forest Bond92b96792009-06-13 07:38:31 -0400991{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100992 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +0100993 struct vnt_tx_fifo_head *pTxBufHead = &tx_buffer->fifo_head;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000994 u32 cbFrameSize, cbFrameBodySize;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000995 u32 cb802_1_H_len;
996 u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbMACHdLen = 0;
997 u32 cbFCSlen = 4, cbMICHDR = 0;
Malcolm Priestleyf46142b2013-08-27 11:56:33 +0100998 int bNeedACK;
999 bool bRTS = false;
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001000 u8 *pbyType, *pbyMacHdr, *pbyIVHead, *pbyPayloadHead;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001001 u8 abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
1002 u8 abySNAP_Bridgetunnel[ETH_ALEN]
1003 = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
1004 u32 uDuration;
1005 u32 cbHeaderLength = 0, uPadding = 0;
Malcolm Priestley5a5d6a82013-08-23 14:33:55 +01001006 struct vnt_mic_hdr *pMICHDR;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001007 u8 byFBOption = AUTO_FB_NONE, byFragType;
Malcolm Priestley4235f722013-08-24 12:42:01 +01001008 u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001009 u32 *pdwMIC_L, *pdwMIC_R;
Andres Moree269fc22013-02-12 20:36:29 -05001010 int bSoftWEP = false;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +01001011
Malcolm Priestleyc545e6a2013-10-01 16:07:25 +01001012 pMICHDR = NULL;
Forest Bond92b96792009-06-13 07:38:31 -04001013
Malcolm Priestleye2efba72012-11-11 15:20:52 +00001014 if (bNeedEncryption && pTransmitKey->pvKeyTable) {
Andres More4e9b5e22013-02-12 20:36:30 -05001015 if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
1016 bSoftWEP = true; /* WEP 256 */
Malcolm Priestleye2efba72012-11-11 15:20:52 +00001017 }
Forest Bond92b96792009-06-13 07:38:31 -04001018
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001019 /* Get pkt type */
1020 if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN)
1021 cb802_1_H_len = 8;
1022 else
1023 cb802_1_H_len = 0;
Forest Bond92b96792009-06-13 07:38:31 -04001024
Charles Clément21ec51f2010-05-18 10:08:14 -07001025 cbFrameBodySize = uSkbPacketLen - ETH_HLEN + cb802_1_H_len;
Forest Bond92b96792009-06-13 07:38:31 -04001026
1027 //Set packet type
Andres More3eaca0d2013-02-25 20:32:52 -05001028 pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8);
Forest Bond92b96792009-06-13 07:38:31 -04001029
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001030 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC ||
1031 pDevice->op_mode == NL80211_IFTYPE_AP) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001032 if (is_multicast_ether_addr(psEthHeader->h_dest)) {
Andres Moree269fc22013-02-12 20:36:29 -05001033 bNeedACK = false;
Andres More22040bb2010-08-02 20:21:44 -03001034 pTxBufHead->wFIFOCtl =
1035 pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
1036 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001037 bNeedACK = true;
Andres More22040bb2010-08-02 20:21:44 -03001038 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1039 }
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001040 } else {
1041 /* MSDUs in Infra mode always need ACK */
1042 bNeedACK = true;
1043 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1044 }
Forest Bond92b96792009-06-13 07:38:31 -04001045
Malcolm Priestley58462512014-03-22 09:01:27 +00001046 pTxBufHead->time_stamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
Forest Bond92b96792009-06-13 07:38:31 -04001047
Forest Bond92b96792009-06-13 07:38:31 -04001048 //Set FRAGCTL_MACHDCNT
Malcolm Priestley078d0cf2013-11-25 22:14:16 +00001049 cbMACHdLen = WLAN_HDR_ADDR3_LEN;
1050
Andres More3eaca0d2013-02-25 20:32:52 -05001051 pTxBufHead->wFragCtl |= (u16)(cbMACHdLen << 10);
Forest Bond92b96792009-06-13 07:38:31 -04001052
1053 //Set FIFOCTL_GrpAckPolicy
Andres More4e9b5e22013-02-12 20:36:30 -05001054 if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
Forest Bond92b96792009-06-13 07:38:31 -04001055 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK;
1056 }
1057
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +01001058 /* Set Auto Fallback Ctl */
1059 if (wCurrentRate >= RATE_18M) {
1060 if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
1061 pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
1062
1063 pDevice->tx_rate_fb0 =
1064 wFB_Opt0[FB_RATE0][wCurrentRate - RATE_18M];
1065 pDevice->tx_rate_fb1 =
1066 wFB_Opt0[FB_RATE1][wCurrentRate - RATE_18M];
1067
1068 byFBOption = AUTO_FB_0;
1069 } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
1070 pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
1071 pDevice->tx_rate_fb0 =
1072 wFB_Opt1[FB_RATE0][wCurrentRate - RATE_18M];
1073 pDevice->tx_rate_fb1 =
1074 wFB_Opt1[FB_RATE1][wCurrentRate - RATE_18M];
1075
1076 byFBOption = AUTO_FB_1;
1077 }
1078 }
Forest Bond92b96792009-06-13 07:38:31 -04001079
Andres More4e9b5e22013-02-12 20:36:30 -05001080 if (bSoftWEP != true) {
Forest Bond92b96792009-06-13 07:38:31 -04001081 if ((bNeedEncryption) && (pTransmitKey != NULL)) { //WEP enabled
1082 if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104
1083 pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
1084 }
1085 if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
1086 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Tx Set wFragCtl == FRAGCTL_TKIP\n");
1087 pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
1088 }
1089 else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP
1090 pTxBufHead->wFragCtl |= FRAGCTL_AES;
1091 }
1092 }
1093 }
1094
Forest Bond92b96792009-06-13 07:38:31 -04001095 if ((bNeedEncryption) && (pTransmitKey != NULL)) {
1096 if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
1097 cbIVlen = 4;
1098 cbICVlen = 4;
1099 }
1100 else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
1101 cbIVlen = 8;//IV+ExtIV
1102 cbMIClen = 8;
1103 cbICVlen = 4;
1104 }
1105 if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
1106 cbIVlen = 8;//RSN Header
1107 cbICVlen = 8;//MIC
Malcolm Priestley5a5d6a82013-08-23 14:33:55 +01001108 cbMICHDR = sizeof(struct vnt_mic_hdr);
Forest Bond92b96792009-06-13 07:38:31 -04001109 }
Andres Moree269fc22013-02-12 20:36:29 -05001110 if (bSoftWEP == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001111 //MAC Header should be padding 0 to DW alignment.
1112 uPadding = 4 - (cbMACHdLen%4);
1113 uPadding %= 4;
1114 }
1115 }
1116
1117 cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
1118
Andres Moree269fc22013-02-12 20:36:29 -05001119 if ( (bNeedACK == false) ||(cbFrameSize < pDevice->wRTSThreshold) ) {
1120 bRTS = false;
Forest Bond92b96792009-06-13 07:38:31 -04001121 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001122 bRTS = true;
Forest Bond92b96792009-06-13 07:38:31 -04001123 pTxBufHead->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY);
1124 }
1125
Forest Bond92b96792009-06-13 07:38:31 -04001126 //=========================
1127 // No Fragmentation
1128 //=========================
1129 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n");
1130 byFragType = FRAGCTL_NONFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001131 //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
1132
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001133 /* Fill FIFO, RrvTime, RTS and CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01001134 uDuration = s_vGenerateTxParameter(tx_context, byPktType, wCurrentRate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001135 tx_buffer, &pMICHDR, cbMICHDR,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001136 cbFrameSize, bNeedACK, psEthHeader, bRTS);
Malcolm Priestleyc12dca02013-10-01 16:03:40 +01001137
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001138 cbHeaderLength = tx_context->tx_hdr_size;
1139 if (!cbHeaderLength)
1140 return false;
1141
1142 pbyMacHdr = (u8 *)tx_context->hdr;
1143 pbyIVHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding);
1144 pbyPayloadHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
1145
1146 /* Generate TX MAC Header */
1147 s_vGenerateMACHeader(pDevice, tx_context->hdr, (u16)uDuration,
1148 psEthHeader, bNeedEncryption, byFragType, 0);
Forest Bond92b96792009-06-13 07:38:31 -04001149
Andres More4e9b5e22013-02-12 20:36:30 -05001150 if (bNeedEncryption == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001151 //Fill TXKEY
Malcolm Priestley3695c462014-05-31 13:34:59 +01001152 s_vFillTxKey(tx_context, pTxBufHead, pbyIVHead, pTransmitKey,
1153 (u16)cbFrameBodySize, pMICHDR);
Forest Bond92b96792009-06-13 07:38:31 -04001154 }
1155
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001156 /* 802.1H */
1157 if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001158 if ((psEthHeader->h_proto == cpu_to_be16(ETH_P_IPX)) ||
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001159 (psEthHeader->h_proto == cpu_to_le16(0xF380)))
Andres Moreb902fbf2013-02-25 20:32:51 -05001160 memcpy((u8 *) (pbyPayloadHead),
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001161 abySNAP_Bridgetunnel, 6);
1162 else
1163 memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6);
Forest Bond92b96792009-06-13 07:38:31 -04001164
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001165 pbyType = (u8 *) (pbyPayloadHead + 6);
Forest Bond92b96792009-06-13 07:38:31 -04001166
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001167 memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16));
1168 }
Forest Bond92b96792009-06-13 07:38:31 -04001169
Forest Bond92b96792009-06-13 07:38:31 -04001170 if (pPacket != NULL) {
1171 // Copy the Packet into a tx Buffer
Jim Lieb3e362592009-08-12 14:54:11 -07001172 memcpy((pbyPayloadHead + cb802_1_H_len),
Charles Clément21ec51f2010-05-18 10:08:14 -07001173 (pPacket + ETH_HLEN),
1174 uSkbPacketLen - ETH_HLEN
Forest Bond92b96792009-06-13 07:38:31 -04001175 );
1176
1177 } else {
1178 // while bRelayPacketSend psEthHeader is point to header+payload
Andres Moreb902fbf2013-02-25 20:32:51 -05001179 memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN);
Forest Bond92b96792009-06-13 07:38:31 -04001180 }
1181
Andres More4e9b5e22013-02-12 20:36:30 -05001182 if ((bNeedEncryption == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
Forest Bond92b96792009-06-13 07:38:31 -04001183
1184 ///////////////////////////////////////////////////////////////////
1185
Malcolm Priestley14c5ef52013-01-17 23:19:37 +00001186 if (pDevice->vnt_mgmt.eAuthenMode == WMAC_AUTH_WPANONE) {
1187 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
1188 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
1189 }
Forest Bond92b96792009-06-13 07:38:31 -04001190 else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) {
Andres More52a7e642013-02-25 20:32:53 -05001191 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
1192 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
Forest Bond92b96792009-06-13 07:38:31 -04001193 }
1194 else {
Andres More52a7e642013-02-25 20:32:53 -05001195 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[24]);
1196 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[28]);
Forest Bond92b96792009-06-13 07:38:31 -04001197 }
1198 // DO Software Michael
1199 MIC_vInit(dwMICKey0, dwMICKey1);
Andres Moreceb8c5d2013-03-18 20:33:49 -05001200 MIC_vAppend((u8 *)&(psEthHeader->h_dest[0]), 12);
Forest Bond92b96792009-06-13 07:38:31 -04001201 dwMIC_Priority = 0;
Andres Moreb902fbf2013-02-25 20:32:51 -05001202 MIC_vAppend((u8 *)&dwMIC_Priority, 4);
Malcolm Priestleyb4dc03a2012-11-11 15:45:52 +00001203 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n",
1204 dwMICKey0, dwMICKey1);
Forest Bond92b96792009-06-13 07:38:31 -04001205
1206 ///////////////////////////////////////////////////////////////////
1207
1208 //DBG_PRN_GRP12(("Length:%d, %d\n", cbFrameBodySize, uFromHDtoPLDLength));
1209 //for (ii = 0; ii < cbFrameBodySize; ii++) {
Andres Moreb902fbf2013-02-25 20:32:51 -05001210 // DBG_PRN_GRP12(("%02x ", *((u8 *)((pbyPayloadHead + cb802_1_H_len) + ii))));
Forest Bond92b96792009-06-13 07:38:31 -04001211 //}
1212 //DBG_PRN_GRP12(("\n\n\n"));
1213
1214 MIC_vAppend(pbyPayloadHead, cbFrameBodySize);
1215
Andres More52a7e642013-02-25 20:32:53 -05001216 pdwMIC_L = (u32 *)(pbyPayloadHead + cbFrameBodySize);
1217 pdwMIC_R = (u32 *)(pbyPayloadHead + cbFrameBodySize + 4);
Forest Bond92b96792009-06-13 07:38:31 -04001218
1219 MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
1220 MIC_vUnInit();
1221
Andres More4e9b5e22013-02-12 20:36:30 -05001222 if (pDevice->bTxMICFail == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001223 *pdwMIC_L = 0;
1224 *pdwMIC_R = 0;
Andres Moree269fc22013-02-12 20:36:29 -05001225 pDevice->bTxMICFail = false;
Forest Bond92b96792009-06-13 07:38:31 -04001226 }
1227 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize);
1228 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen);
1229 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
1230 }
1231
Andres More4e9b5e22013-02-12 20:36:30 -05001232 if (bSoftWEP == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001233
Andres More3eaca0d2013-02-25 20:32:52 -05001234 s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (u16)(cbFrameBodySize + cbMIClen));
Forest Bond92b96792009-06-13 07:38:31 -04001235
Andres More4e9b5e22013-02-12 20:36:30 -05001236 } else if ( ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) && (bNeedEncryption == true)) ||
1237 ((pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) && (bNeedEncryption == true)) ||
1238 ((pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) && (bNeedEncryption == true)) ) {
Forest Bond92b96792009-06-13 07:38:31 -04001239 cbFrameSize -= cbICVlen;
1240 }
1241
Forest Bond92b96792009-06-13 07:38:31 -04001242 cbFrameSize -= cbFCSlen;
Forest Bond92b96792009-06-13 07:38:31 -04001243
1244 *pcbHeaderLen = cbHeaderLength;
1245 *pcbTotalLen = cbHeaderLength + cbFrameSize ;
1246
Forest Bond92b96792009-06-13 07:38:31 -04001247 //Set FragCtl in TxBufferHead
Andres More3eaca0d2013-02-25 20:32:52 -05001248 pTxBufHead->wFragCtl |= (u16)byFragType;
Forest Bond92b96792009-06-13 07:38:31 -04001249
Andres More4e9b5e22013-02-12 20:36:30 -05001250 return true;
Forest Bond92b96792009-06-13 07:38:31 -04001251
1252}
1253
Forest Bond92b96792009-06-13 07:38:31 -04001254/*+
1255 *
1256 * Description:
1257 * Translate 802.3 to 802.11 header
1258 *
1259 * Parameters:
1260 * In:
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001261 * pDevice - Pointer to adapter
Forest Bond92b96792009-06-13 07:38:31 -04001262 * dwTxBufferAddr - Transmit Buffer
1263 * pPacket - Packet from upper layer
1264 * cbPacketSize - Transmit Data Length
1265 * Out:
1266 * pcbHeadSize - Header size of MAC&Baseband control and 802.11 Header
1267 * pcbAppendPayload - size of append payload for 802.1H translation
1268 *
1269 * Return Value: none
1270 *
1271-*/
1272
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001273static void s_vGenerateMACHeader(struct vnt_private *pDevice,
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001274 struct ieee80211_hdr *pMACHeader, u16 wDuration,
1275 struct ethhdr *psEthHeader, int bNeedEncrypt, u16 wFragType,
1276 u32 uFragIdx)
Forest Bond92b96792009-06-13 07:38:31 -04001277{
Forest Bond92b96792009-06-13 07:38:31 -04001278
Malcolm Priestleyc921cc82013-08-20 20:47:49 +01001279 pMACHeader->frame_control = TYPE_802_11_DATA;
Forest Bond92b96792009-06-13 07:38:31 -04001280
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001281 if (pDevice->op_mode == NL80211_IFTYPE_AP) {
Andres More1cac4a42013-03-18 20:33:50 -05001282 memcpy(&(pMACHeader->addr1[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001283 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001284 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001285 memcpy(&(pMACHeader->addr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
1286 memcpy(&(pMACHeader->addr3[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001287 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001288 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001289 pMACHeader->frame_control |= FC_FROMDS;
Andres More9a0e7562010-04-13 21:54:48 -03001290 } else {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001291 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
Andres More1cac4a42013-03-18 20:33:50 -05001292 memcpy(&(pMACHeader->addr1[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001293 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001294 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001295 memcpy(&(pMACHeader->addr2[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001296 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001297 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001298 memcpy(&(pMACHeader->addr3[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001299 &(pDevice->abyBSSID[0]),
1300 ETH_ALEN);
1301 } else {
Andres More1cac4a42013-03-18 20:33:50 -05001302 memcpy(&(pMACHeader->addr3[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001303 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001304 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001305 memcpy(&(pMACHeader->addr2[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001306 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001307 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001308 memcpy(&(pMACHeader->addr1[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001309 &(pDevice->abyBSSID[0]),
1310 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001311 pMACHeader->frame_control |= FC_TODS;
Forest Bond92b96792009-06-13 07:38:31 -04001312 }
1313 }
1314
1315 if (bNeedEncrypt)
Andres More1cac4a42013-03-18 20:33:50 -05001316 pMACHeader->frame_control |= cpu_to_le16((u16)WLAN_SET_FC_ISWEP(1));
Forest Bond92b96792009-06-13 07:38:31 -04001317
Andres More1cac4a42013-03-18 20:33:50 -05001318 pMACHeader->duration_id = cpu_to_le16(wDuration);
Forest Bond92b96792009-06-13 07:38:31 -04001319
Andres More1cac4a42013-03-18 20:33:50 -05001320 pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
Forest Bond92b96792009-06-13 07:38:31 -04001321
1322 //Set FragNumber in Sequence Control
Andres More1cac4a42013-03-18 20:33:50 -05001323 pMACHeader->seq_ctrl |= cpu_to_le16((u16)uFragIdx);
Forest Bond92b96792009-06-13 07:38:31 -04001324
1325 if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
1326 pDevice->wSeqCounter++;
1327 if (pDevice->wSeqCounter > 0x0fff)
1328 pDevice->wSeqCounter = 0;
1329 }
1330
1331 if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag
Andres More1cac4a42013-03-18 20:33:50 -05001332 pMACHeader->frame_control |= FC_MOREFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001333 }
1334}
1335
Forest Bond92b96792009-06-13 07:38:31 -04001336/*+
1337 *
1338 * Description:
1339 * Request instructs a MAC to transmit a 802.11 management packet through
1340 * the adapter onto the medium.
1341 *
1342 * Parameters:
1343 * In:
1344 * hDeviceContext - Pointer to the adapter
1345 * pPacket - A pointer to a descriptor for the packet to transmit
1346 * Out:
1347 * none
1348 *
Andres Moree269fc22013-02-12 20:36:29 -05001349 * Return Value: CMD_STATUS_PENDING if MAC Tx resource available; otherwise false
Forest Bond92b96792009-06-13 07:38:31 -04001350 *
1351-*/
1352
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001353CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
1354 struct vnt_tx_mgmt *pPacket)
Forest Bond92b96792009-06-13 07:38:31 -04001355{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001356 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
Malcolm Priestleyf39c0d82013-08-15 19:34:37 +01001357 struct vnt_tx_buffer *pTX_Buffer;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001358 struct vnt_usb_send_context *pContext;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001359 struct vnt_tx_fifo_head *pTxBufHead;
Andres More1cac4a42013-03-18 20:33:50 -05001360 struct ieee80211_hdr *pMACHeader;
Andres Moreceb8c5d2013-03-18 20:33:49 -05001361 struct ethhdr sEthHeader;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001362 u8 byPktType, *pbyTxBufferAddr;
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +01001363 struct vnt_mic_hdr *pMICHDR = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001364 u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
Andres Moree269fc22013-02-12 20:36:29 -05001365 int bNeedACK, bIsPSPOLL = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001366 u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
1367 u32 uPadding = 0;
1368 u16 wTxBufSize;
1369 u32 cbMacHdLen;
1370 u16 wCurrentRate = RATE_1M;
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001371 unsigned long flags;
1372
1373 if (pDevice->byBBType == BB_TYPE_11A) {
1374 wCurrentRate = RATE_6M;
1375 byPktType = PK_TYPE_11A;
1376 } else {
1377 wCurrentRate = RATE_1M;
1378 byPktType = PK_TYPE_11B;
1379 }
1380
1381 if (pMgmt->eScanState != WMAC_NO_SCANNING)
Malcolm Priestley4f5290e2014-05-27 21:05:21 +01001382 vnt_rf_setpower(pDevice, wCurrentRate, pDevice->byCurrentCh);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001383 else
Malcolm Priestley4f5290e2014-05-27 21:05:21 +01001384 vnt_rf_setpower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001385
1386 pDevice->wCurrentRate = wCurrentRate;
1387
1388 spin_lock_irqsave(&pDevice->lock, flags);
Forest Bond92b96792009-06-13 07:38:31 -04001389
Malcolm Priestleyaceaf012013-11-26 19:06:35 +00001390 pContext = s_vGetFreeContext(pDevice);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001391 if (!pContext) {
1392 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
1393 "ManagementSend TX...NO CONTEXT!\n");
1394 spin_unlock_irqrestore(&pDevice->lock, flags);
1395 return CMD_STATUS_RESOURCES;
1396 }
Forest Bond92b96792009-06-13 07:38:31 -04001397
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001398 pTX_Buffer = (struct vnt_tx_buffer *)&pContext->data[0];
Forest Bond92b96792009-06-13 07:38:31 -04001399 cbFrameBodySize = pPacket->cbPayloadLen;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001400 pTxBufHead = &pTX_Buffer->fifo_head;
Malcolm Priestleyab51f512014-05-31 13:35:00 +01001401 pbyTxBufferAddr = (u8 *)pTxBufHead;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001402 wTxBufSize = sizeof(struct vnt_tx_fifo_head);
Forest Bond92b96792009-06-13 07:38:31 -04001403
Forest Bond92b96792009-06-13 07:38:31 -04001404
Forest Bond92b96792009-06-13 07:38:31 -04001405 //Set packet type
1406 if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
1407 pTxBufHead->wFIFOCtl = 0;
1408 }
1409 else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
1410 pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
1411 }
1412 else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
1413 pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
1414 }
1415 else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
1416 pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
1417 }
1418
1419 pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
Malcolm Priestley58462512014-03-22 09:01:27 +00001420 pTxBufHead->time_stamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
Forest Bond92b96792009-06-13 07:38:31 -04001421
Andres More22040bb2010-08-02 20:21:44 -03001422 if (is_multicast_ether_addr(pPacket->p80211Header->sA3.abyAddr1)) {
Andres Moree269fc22013-02-12 20:36:29 -05001423 bNeedACK = false;
Forest Bond92b96792009-06-13 07:38:31 -04001424 }
1425 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001426 bNeedACK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001427 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1428 };
1429
1430 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
1431 (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) {
1432
1433 pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
1434 //Set Preamble type always long
1435 //pDevice->byPreambleType = PREAMBLE_LONG;
1436 // probe-response don't retry
1437 //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) {
Andres Moree269fc22013-02-12 20:36:29 -05001438 // bNeedACK = false;
Forest Bond92b96792009-06-13 07:38:31 -04001439 // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK);
1440 //}
1441 }
1442
1443 pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
1444
1445 if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
Andres More4e9b5e22013-02-12 20:36:30 -05001446 bIsPSPOLL = true;
Forest Bond92b96792009-06-13 07:38:31 -04001447 cbMacHdLen = WLAN_HDR_ADDR2_LEN;
1448 } else {
1449 cbMacHdLen = WLAN_HDR_ADDR3_LEN;
1450 }
1451
1452 //Set FRAGCTL_MACHDCNT
Andres More3eaca0d2013-02-25 20:32:52 -05001453 pTxBufHead->wFragCtl |= cpu_to_le16((u16)(cbMacHdLen << 10));
Forest Bond92b96792009-06-13 07:38:31 -04001454
1455 // Notes:
1456 // Although spec says MMPDU can be fragmented; In most case,
1457 // no one will send a MMPDU under fragmentation. With RTS may occur.
Forest Bond92b96792009-06-13 07:38:31 -04001458
1459 if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
1460 if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
1461 cbIVlen = 4;
1462 cbICVlen = 4;
1463 pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
1464 }
1465 else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
1466 cbIVlen = 8;//IV+ExtIV
1467 cbMIClen = 8;
1468 cbICVlen = 4;
1469 pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
1470 //We need to get seed here for filling TxKey entry.
1471 //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
1472 // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
1473 }
1474 else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
1475 cbIVlen = 8;//RSN Header
1476 cbICVlen = 8;//MIC
1477 pTxBufHead->wFragCtl |= FRAGCTL_AES;
Forest Bond92b96792009-06-13 07:38:31 -04001478 }
1479 //MAC Header should be padding 0 to DW alignment.
1480 uPadding = 4 - (cbMacHdLen%4);
1481 uPadding %= 4;
1482 }
1483
1484 cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen;
1485
1486 //Set FIFOCTL_GrpAckPolicy
Andres More4e9b5e22013-02-12 20:36:30 -05001487 if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
Forest Bond92b96792009-06-13 07:38:31 -04001488 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK;
1489 }
1490 //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
1491
Andres Moreceb8c5d2013-03-18 20:33:49 -05001492 memcpy(&(sEthHeader.h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001493 &(pPacket->p80211Header->sA3.abyAddr1[0]),
1494 ETH_ALEN);
Andres Moreceb8c5d2013-03-18 20:33:49 -05001495 memcpy(&(sEthHeader.h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001496 &(pPacket->p80211Header->sA3.abyAddr2[0]),
1497 ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -04001498 //=========================
1499 // No Fragmentation
1500 //=========================
Andres More3eaca0d2013-02-25 20:32:52 -05001501 pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001502
Malcolm Priestley351c7dc2013-08-27 12:02:54 +01001503 /* Fill FIFO,RrvTime,RTS,and CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01001504 uDuration = s_vGenerateTxParameter(pContext, byPktType, wCurrentRate,
Malcolm Priestleyfa575602013-09-26 19:00:41 +01001505 pTX_Buffer, &pMICHDR, 0,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001506 cbFrameSize, bNeedACK, &sEthHeader, false);
Forest Bond92b96792009-06-13 07:38:31 -04001507
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001508 cbHeaderSize = pContext->tx_hdr_size;
1509 if (!cbHeaderSize) {
1510 pContext->in_use = false;
1511 return CMD_STATUS_RESOURCES;
1512 }
1513
1514 pMACHeader = pContext->hdr;
Forest Bond92b96792009-06-13 07:38:31 -04001515
1516 cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
1517
1518 if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
Andres Moreb902fbf2013-02-25 20:32:51 -05001519 u8 * pbyIVHead;
1520 u8 * pbyPayloadHead;
1521 u8 * pbyBSSID;
Forest Bond92b96792009-06-13 07:38:31 -04001522 PSKeyItem pTransmitKey = NULL;
1523
Andres Moreb902fbf2013-02-25 20:32:51 -05001524 pbyIVHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
1525 pbyPayloadHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
Forest Bond92b96792009-06-13 07:38:31 -04001526 do {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001527 if (pDevice->op_mode == NL80211_IFTYPE_STATION &&
1528 pDevice->bLinkPass == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001529 pbyBSSID = pDevice->abyBSSID;
1530 // get pairwise key
Andres Moree269fc22013-02-12 20:36:29 -05001531 if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001532 // get group key
Andres More4e9b5e22013-02-12 20:36:30 -05001533 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001534 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
1535 break;
1536 }
1537 } else {
1538 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n");
1539 break;
1540 }
1541 }
1542 // get group key
1543 pbyBSSID = pDevice->abyBroadcastAddr;
Andres Moree269fc22013-02-12 20:36:29 -05001544 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001545 pTransmitKey = NULL;
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001546 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->op_mode);
Forest Bond92b96792009-06-13 07:38:31 -04001547 } else {
1548 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
1549 }
Andres Moree269fc22013-02-12 20:36:29 -05001550 } while(false);
Forest Bond92b96792009-06-13 07:38:31 -04001551 //Fill TXKEY
Malcolm Priestley3695c462014-05-31 13:34:59 +01001552 s_vFillTxKey(pContext, pTxBufHead, pbyIVHead, pTransmitKey,
1553 (u16)cbFrameBodySize, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001554
Jim Lieb3e362592009-08-12 14:54:11 -07001555 memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
Andres Moreb902fbf2013-02-25 20:32:51 -05001556 memcpy(pbyPayloadHead, ((u8 *)(pPacket->p80211Header) + cbMacHdLen),
Forest Bond92b96792009-06-13 07:38:31 -04001557 cbFrameBodySize);
1558 }
1559 else {
1560 // Copy the Packet into a tx Buffer
Jim Lieb3e362592009-08-12 14:54:11 -07001561 memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
Forest Bond92b96792009-06-13 07:38:31 -04001562 }
1563
Andres More1cac4a42013-03-18 20:33:50 -05001564 pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
Forest Bond92b96792009-06-13 07:38:31 -04001565 pDevice->wSeqCounter++ ;
1566 if (pDevice->wSeqCounter > 0x0fff)
1567 pDevice->wSeqCounter = 0;
1568
1569 if (bIsPSPOLL) {
1570 // The MAC will automatically replace the Duration-field of MAC header by Duration-field
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001571 // of FIFO control header.
Forest Bond92b96792009-06-13 07:38:31 -04001572 // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is
1573 // in the same place of other packet's Duration-field).
1574 // And it will cause Cisco-AP to issue Disassociation-packet
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001575 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001576 struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
1577 tx_cts.tx.head.cts_g.data_head;
Malcolm Priestley4e011172014-03-18 19:24:55 +00001578 data_head->duration_a =
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001579 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
Malcolm Priestley4e011172014-03-18 19:24:55 +00001580 data_head->duration_b =
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001581 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
1582 } else {
Malcolm Priestleyc12dca02013-10-01 16:03:40 +01001583 struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
1584 tx_ab.tx.head.data_head_ab;
Malcolm Priestley4e011172014-03-18 19:24:55 +00001585 data_head->duration =
Malcolm Priestley558becf2013-08-16 23:50:32 +01001586 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
1587 }
Forest Bond92b96792009-06-13 07:38:31 -04001588 }
1589
Malcolm Priestleyca347592014-03-22 09:01:28 +00001590 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)(cbReqCount));
Andres Moreb902fbf2013-02-25 20:32:51 -05001591 pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Forest Bond92b96792009-06-13 07:38:31 -04001592 pTX_Buffer->byType = 0x00;
1593
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001594 pContext->skb = NULL;
1595 pContext->type = CONTEXT_MGMT_PACKET;
1596 pContext->buf_len = (u16)cbReqCount + 4; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04001597
Andres More1cac4a42013-03-18 20:33:50 -05001598 if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001599 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
1600 &pMACHeader->addr1[0], (u16)cbFrameSize,
1601 pTxBufHead->wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04001602 }
1603 else {
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001604 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
1605 &pMACHeader->addr3[0], (u16)cbFrameSize,
1606 pTxBufHead->wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04001607 }
1608
1609 PIPEnsSendBulkOut(pDevice,pContext);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001610
1611 spin_unlock_irqrestore(&pDevice->lock, flags);
1612
Forest Bond92b96792009-06-13 07:38:31 -04001613 return CMD_STATUS_PENDING;
1614}
1615
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001616CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
1617 struct vnt_tx_mgmt *pPacket)
Forest Bond92b96792009-06-13 07:38:31 -04001618{
Malcolm Priestley01f865b2013-08-15 19:40:08 +01001619 struct vnt_beacon_buffer *pTX_Buffer;
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001620 struct vnt_tx_short_buf_head *short_head;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001621 u32 cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN;
1622 u32 cbHeaderSize = 0;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001623 u16 wCurrentRate;
1624 u32 cbFrameBodySize;
1625 u32 cbReqCount;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001626 struct vnt_usb_send_context *pContext;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001627 CMD_STATUS status;
Forest Bond92b96792009-06-13 07:38:31 -04001628
Malcolm Priestleyaceaf012013-11-26 19:06:35 +00001629 pContext = s_vGetFreeContext(pDevice);
Forest Bond92b96792009-06-13 07:38:31 -04001630 if (NULL == pContext) {
1631 status = CMD_STATUS_RESOURCES;
1632 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n");
1633 return status ;
1634 }
Malcolm Priestley01f865b2013-08-15 19:40:08 +01001635
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001636 pTX_Buffer = (struct vnt_beacon_buffer *)&pContext->data[0];
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001637 short_head = &pTX_Buffer->short_head;
Forest Bond92b96792009-06-13 07:38:31 -04001638
1639 cbFrameBodySize = pPacket->cbPayloadLen;
1640
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001641 cbHeaderSize = sizeof(struct vnt_tx_short_buf_head);
Forest Bond92b96792009-06-13 07:38:31 -04001642
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001643 if (pDevice->byBBType == BB_TYPE_11A) {
1644 wCurrentRate = RATE_6M;
1645
1646 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +01001647 vnt_get_phy_field(pDevice, cbFrameSize, wCurrentRate,
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001648 PK_TYPE_11A, &short_head->ab);
1649
1650 /* Get Duration and TimeStampOff */
1651 short_head->duration = s_uGetDataDuration(pDevice,
1652 PK_TYPE_11A, false);
1653 short_head->time_stamp_off =
1654 vnt_time_stamp_off(pDevice, wCurrentRate);
1655 } else {
1656 wCurrentRate = RATE_1M;
1657 short_head->fifo_ctl |= FIFOCTL_11B;
1658
1659 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +01001660 vnt_get_phy_field(pDevice, cbFrameSize, wCurrentRate,
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001661 PK_TYPE_11B, &short_head->ab);
1662
1663 /* Get Duration and TimeStampOff */
1664 short_head->duration = s_uGetDataDuration(pDevice,
Malcolm Priestley6b5ad9d2013-08-21 22:16:04 +01001665 PK_TYPE_11B, false);
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001666 short_head->time_stamp_off =
1667 vnt_time_stamp_off(pDevice, wCurrentRate);
1668 }
1669
Forest Bond92b96792009-06-13 07:38:31 -04001670
Malcolm Priestley0b71fe32013-11-24 13:27:32 +00001671 /* Generate Beacon Header */
Malcolm Priestley0b71fe32013-11-24 13:27:32 +00001672 pDevice->wSeqCounter++;
1673 if (pDevice->wSeqCounter > 0x0fff)
1674 pDevice->wSeqCounter = 0;
Forest Bond92b96792009-06-13 07:38:31 -04001675
1676 cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize;
1677
Malcolm Priestleyfad8e4a2014-03-22 09:01:29 +00001678 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)cbReqCount);
Andres Moreb902fbf2013-02-25 20:32:51 -05001679 pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Forest Bond92b96792009-06-13 07:38:31 -04001680 pTX_Buffer->byType = 0x01;
1681
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001682 pContext->skb = NULL;
1683 pContext->type = CONTEXT_MGMT_PACKET;
1684 pContext->buf_len = (u16)cbReqCount + 4; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04001685
1686 PIPEnsSendBulkOut(pDevice,pContext);
1687 return CMD_STATUS_PENDING;
1688
1689}
1690
Forest Bond92b96792009-06-13 07:38:31 -04001691//TYPE_AC0DMA data tx
1692/*
1693 * Description:
1694 * Tx packet via AC0DMA(DMA1)
1695 *
1696 * Parameters:
1697 * In:
1698 * pDevice - Pointer to the adapter
1699 * skb - Pointer to tx skb packet
1700 * Out:
1701 * void
1702 *
1703 * Return Value: NULL
1704 */
1705
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001706int nsDMA_tx_packet(struct vnt_private *pDevice, struct sk_buff *skb)
Forest Bond92b96792009-06-13 07:38:31 -04001707{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001708 struct net_device_stats *pStats = &pDevice->stats;
1709 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
Malcolm Priestleyf39c0d82013-08-15 19:34:37 +01001710 struct vnt_tx_buffer *pTX_Buffer;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001711 u32 BytesToWrite = 0, uHeaderLen = 0;
1712 u32 uNodeIndex = 0;
1713 u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
1714 u16 wAID;
1715 u8 byPktType;
Andres Moree269fc22013-02-12 20:36:29 -05001716 int bNeedEncryption = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001717 PSKeyItem pTransmitKey = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001718 int ii;
Andres Moree269fc22013-02-12 20:36:29 -05001719 int bTKIP_UseGTK = false;
1720 int bNeedDeAuth = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001721 u8 *pbyBSSID;
Andres Moree269fc22013-02-12 20:36:29 -05001722 int bNodeExist = false;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001723 struct vnt_usb_send_context *pContext;
Andres Moredfdcc422013-02-12 20:36:28 -05001724 bool fConvertedPacket;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001725 u32 status;
1726 u16 wKeepRate = pDevice->wCurrentRate;
Andres Moree269fc22013-02-12 20:36:29 -05001727 int bTxeapol_key = false;
Forest Bond92b96792009-06-13 07:38:31 -04001728
Forest Bond92b96792009-06-13 07:38:31 -04001729 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
1730
1731 if (pDevice->uAssocCount == 0) {
1732 dev_kfree_skb_irq(skb);
1733 return 0;
1734 }
1735
Andres Moreb902fbf2013-02-25 20:32:51 -05001736 if (is_multicast_ether_addr((u8 *)(skb->data))) {
Forest Bond92b96792009-06-13 07:38:31 -04001737 uNodeIndex = 0;
Andres More4e9b5e22013-02-12 20:36:30 -05001738 bNodeExist = true;
Forest Bond92b96792009-06-13 07:38:31 -04001739 if (pMgmt->sNodeDBTable[0].bPSEnable) {
1740
1741 skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
1742 pMgmt->sNodeDBTable[0].wEnQueueCnt++;
1743 // set tx map
1744 pMgmt->abyPSTxMap[0] |= byMask[0];
1745 return 0;
1746 }
Masanari Iida93184692012-08-13 21:21:50 +09001747 // multicast/broadcast data rate
Forest Bond92b96792009-06-13 07:38:31 -04001748
1749 if (pDevice->byBBType != BB_TYPE_11A)
1750 pDevice->wCurrentRate = RATE_2M;
1751 else
1752 pDevice->wCurrentRate = RATE_24M;
1753 // long preamble type
1754 pDevice->byPreambleType = PREAMBLE_SHORT;
1755
1756 }else {
1757
Andres Moreb902fbf2013-02-25 20:32:51 -05001758 if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data), &uNodeIndex)) {
Forest Bond92b96792009-06-13 07:38:31 -04001759
1760 if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
1761
1762 skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
1763
1764 pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
1765 // set tx map
1766 wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
1767 pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7];
1768 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
1769 (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
1770
1771 return 0;
1772 }
1773 // AP rate decided from node
1774 pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
1775 // tx preamble decided from node
1776
1777 if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
1778 pDevice->byPreambleType = pDevice->byShortPreamble;
1779
1780 }else {
1781 pDevice->byPreambleType = PREAMBLE_LONG;
1782 }
Andres More4e9b5e22013-02-12 20:36:30 -05001783 bNodeExist = true;
Forest Bond92b96792009-06-13 07:38:31 -04001784 }
1785 }
1786
Andres Moree269fc22013-02-12 20:36:29 -05001787 if (bNodeExist == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001788 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n");
1789 dev_kfree_skb_irq(skb);
1790 return 0;
1791 }
1792 }
1793
Tobias Klauser838c2d62014-04-25 11:53:58 +02001794 memcpy(&pDevice->sTxEthHeader, skb->data, ETH_HLEN);
Forest Bond92b96792009-06-13 07:38:31 -04001795
1796//mike add:station mode check eapol-key challenge--->
1797{
Andres Moreb902fbf2013-02-25 20:32:51 -05001798 u8 Protocol_Version; //802.1x Authentication
1799 u8 Packet_Type; //802.1x Authentication
1800 u8 Descriptor_type;
Andres More3eaca0d2013-02-25 20:32:52 -05001801 u16 Key_info;
Forest Bond92b96792009-06-13 07:38:31 -04001802
Charles Clément21ec51f2010-05-18 10:08:14 -07001803 Protocol_Version = skb->data[ETH_HLEN];
1804 Packet_Type = skb->data[ETH_HLEN+1];
1805 Descriptor_type = skb->data[ETH_HLEN+1+1+2];
1806 Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
Andres Moreceb8c5d2013-03-18 20:33:49 -05001807 if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001808 /* 802.1x OR eapol-key challenge frame transfer */
1809 if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
1810 (Packet_Type == 3)) {
Andres More4e9b5e22013-02-12 20:36:30 -05001811 bTxeapol_key = true;
Forest Bond92b96792009-06-13 07:38:31 -04001812 if(!(Key_info & BIT3) && //WPA or RSN group-key challenge
1813 (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key
1814 if(Descriptor_type==254) {
Andres More4e9b5e22013-02-12 20:36:30 -05001815 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001816 PRINT_K("WPA ");
1817 }
1818 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001819 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001820 PRINT_K("WPA2(re-keying) ");
1821 }
1822 PRINT_K("Authentication completed!!\n");
1823 }
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001824 else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairwise-key challenge
Forest Bond92b96792009-06-13 07:38:31 -04001825 (Key_info & BIT8) && (Key_info & BIT9)) {
Andres More4e9b5e22013-02-12 20:36:30 -05001826 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001827 PRINT_K("WPA2 Authentication completed!!\n");
1828 }
1829 }
1830 }
1831}
1832//mike add:station mode check eapol-key challenge<---
1833
Andres More4e9b5e22013-02-12 20:36:30 -05001834 if (pDevice->bEncryptionEnable == true) {
1835 bNeedEncryption = true;
Forest Bond92b96792009-06-13 07:38:31 -04001836 // get Transmit key
1837 do {
1838 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
1839 (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
1840 pbyBSSID = pDevice->abyBSSID;
1841 // get pairwise key
Andres Moree269fc22013-02-12 20:36:29 -05001842 if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001843 // get group key
Andres More4e9b5e22013-02-12 20:36:30 -05001844 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
1845 bTKIP_UseGTK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001846 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
1847 break;
1848 }
1849 } else {
1850 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n");
1851 break;
1852 }
1853 }else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001854 /* TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 */
1855 pbyBSSID = pDevice->sTxEthHeader.h_dest;
Forest Bond92b96792009-06-13 07:38:31 -04001856 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n");
1857 for (ii = 0; ii< 6; ii++)
1858 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii));
1859 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n");
1860
1861 // get pairwise key
Andres More4e9b5e22013-02-12 20:36:30 -05001862 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
Forest Bond92b96792009-06-13 07:38:31 -04001863 break;
1864 }
1865 // get group key
1866 pbyBSSID = pDevice->abyBroadcastAddr;
Andres Moree269fc22013-02-12 20:36:29 -05001867 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001868 pTransmitKey = NULL;
1869 if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
1870 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode);
1871 }
1872 else
1873 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode);
1874 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001875 bTKIP_UseGTK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001876 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
1877 }
Andres Moree269fc22013-02-12 20:36:29 -05001878 } while(false);
Forest Bond92b96792009-06-13 07:38:31 -04001879 }
1880
Andres Moreb902fbf2013-02-25 20:32:51 -05001881 byPktType = (u8)pDevice->byPacketType;
Forest Bond92b96792009-06-13 07:38:31 -04001882
1883 if (pDevice->bFixRate) {
1884 if (pDevice->byBBType == BB_TYPE_11B) {
1885 if (pDevice->uConnectionRate >= RATE_11M) {
1886 pDevice->wCurrentRate = RATE_11M;
1887 } else {
Andres More3eaca0d2013-02-25 20:32:52 -05001888 pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
Forest Bond92b96792009-06-13 07:38:31 -04001889 }
1890 } else {
1891 if ((pDevice->byBBType == BB_TYPE_11A) &&
1892 (pDevice->uConnectionRate <= RATE_6M)) {
1893 pDevice->wCurrentRate = RATE_6M;
1894 } else {
1895 if (pDevice->uConnectionRate >= RATE_54M)
1896 pDevice->wCurrentRate = RATE_54M;
1897 else
Andres More3eaca0d2013-02-25 20:32:52 -05001898 pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
Forest Bond92b96792009-06-13 07:38:31 -04001899 }
1900 }
1901 }
1902 else {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001903 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
Forest Bond92b96792009-06-13 07:38:31 -04001904 // Adhoc Tx rate decided from node DB
Andres Moreceb8c5d2013-03-18 20:33:49 -05001905 if (is_multicast_ether_addr(pDevice->sTxEthHeader.h_dest)) {
Forest Bond92b96792009-06-13 07:38:31 -04001906 // Multicast use highest data rate
1907 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
1908 // preamble type
1909 pDevice->byPreambleType = pDevice->byShortPreamble;
1910 }
1911 else {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001912 if (BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.h_dest[0]), &uNodeIndex)) {
Forest Bond92b96792009-06-13 07:38:31 -04001913 pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
1914 if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
1915 pDevice->byPreambleType = pDevice->byShortPreamble;
1916
1917 }
1918 else {
1919 pDevice->byPreambleType = PREAMBLE_LONG;
1920 }
1921 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Found Node Index is [%d] Tx Data Rate:[%d]\n",uNodeIndex, pDevice->wCurrentRate);
1922 }
1923 else {
1924 if (pDevice->byBBType != BB_TYPE_11A)
1925 pDevice->wCurrentRate = RATE_2M;
1926 else
1927 pDevice->wCurrentRate = RATE_24M; // refer to vMgrCreateOwnIBSS()'s
1928 // abyCurrExtSuppRates[]
1929 pDevice->byPreambleType = PREAMBLE_SHORT;
1930 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Not Found Node use highest basic Rate.....\n");
1931 }
1932 }
1933 }
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001934 if (pDevice->op_mode == NL80211_IFTYPE_STATION) {
Forest Bond92b96792009-06-13 07:38:31 -04001935 // Infra STA rate decided from AP Node, index = 0
1936 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
1937 }
1938 }
1939
Andres Moreceb8c5d2013-03-18 20:33:49 -05001940 if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001941 if (pDevice->byBBType != BB_TYPE_11A) {
1942 pDevice->wCurrentRate = RATE_1M;
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001943 pDevice->byTopCCKBasicRate = RATE_1M;
1944 pDevice->byTopOFDMBasicRate = RATE_6M;
1945 } else {
1946 pDevice->wCurrentRate = RATE_6M;
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001947 pDevice->byTopCCKBasicRate = RATE_1M;
1948 pDevice->byTopOFDMBasicRate = RATE_6M;
1949 }
1950 }
Forest Bond92b96792009-06-13 07:38:31 -04001951
Andres More0cbd8d92010-05-06 20:34:29 -03001952 DBG_PRT(MSG_LEVEL_DEBUG,
1953 KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n",
1954 pDevice->wCurrentRate);
Forest Bond92b96792009-06-13 07:38:31 -04001955
1956 if (wKeepRate != pDevice->wCurrentRate) {
Andres More0cbd8d92010-05-06 20:34:29 -03001957 bScheduleCommand((void *) pDevice, WLAN_CMD_SETPOWER, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001958 }
1959
1960 if (pDevice->wCurrentRate <= RATE_11M) {
1961 byPktType = PK_TYPE_11B;
1962 }
1963
Andres More4e9b5e22013-02-12 20:36:30 -05001964 if (bNeedEncryption == true) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001965 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.h_proto));
1966 if ((pDevice->sTxEthHeader.h_proto) == cpu_to_be16(ETH_P_PAE)) {
Andres Moree269fc22013-02-12 20:36:29 -05001967 bNeedEncryption = false;
Andres Moreceb8c5d2013-03-18 20:33:49 -05001968 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.h_proto));
Forest Bond92b96792009-06-13 07:38:31 -04001969 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
1970 if (pTransmitKey == NULL) {
1971 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n");
1972 }
1973 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001974 if (bTKIP_UseGTK == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001975 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n");
1976 }
1977 else {
Malcolm Priestleyb4dc03a2012-11-11 15:45:52 +00001978 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n",
1979 pTransmitKey->dwKeyIndex);
Andres More4e9b5e22013-02-12 20:36:30 -05001980 bNeedEncryption = true;
Forest Bond92b96792009-06-13 07:38:31 -04001981 }
1982 }
1983 }
Forest Bond92b96792009-06-13 07:38:31 -04001984 }
1985 else {
1986
Forest Bond92b96792009-06-13 07:38:31 -04001987 if (pTransmitKey == NULL) {
1988 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n");
1989 dev_kfree_skb_irq(skb);
1990 pStats->tx_dropped++;
1991 return STATUS_FAILURE;
1992 }
Forest Bond92b96792009-06-13 07:38:31 -04001993 }
1994 }
1995
Malcolm Priestleyb674ee12014-05-15 22:49:10 +01001996 pContext = s_vGetFreeContext(pDevice);
1997 if (!pContext) {
1998 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG" pContext == NULL\n");
1999 dev_kfree_skb_irq(skb);
2000 return STATUS_RESOURCES;
2001 }
2002
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002003 pTX_Buffer = (struct vnt_tx_buffer *)&pContext->data[0];
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +01002004
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01002005 fConvertedPacket = s_bPacketToWirelessUsb(pContext, byPktType,
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +01002006 pTX_Buffer, bNeedEncryption,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01002007 skb->len, &pDevice->sTxEthHeader,
Andres Moreb902fbf2013-02-25 20:32:51 -05002008 (u8 *)skb->data, pTransmitKey, uNodeIndex,
Forest Bond92b96792009-06-13 07:38:31 -04002009 pDevice->wCurrentRate,
2010 &uHeaderLen, &BytesToWrite
2011 );
2012
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002013 if (fConvertedPacket == false) {
2014 pContext->in_use = false;
2015 dev_kfree_skb_irq(skb);
2016 return STATUS_FAILURE;
2017 }
Forest Bond92b96792009-06-13 07:38:31 -04002018
Andres More4e9b5e22013-02-12 20:36:30 -05002019 if ( pDevice->bEnablePSMode == true ) {
Forest Bond92b96792009-06-13 07:38:31 -04002020 if ( !pDevice->bPSModeTxBurst ) {
Andres More0cbd8d92010-05-06 20:34:29 -03002021 bScheduleCommand((void *) pDevice,
2022 WLAN_CMD_MAC_DISPOWERSAVING,
2023 NULL);
Andres More4e9b5e22013-02-12 20:36:30 -05002024 pDevice->bPSModeTxBurst = true;
Forest Bond92b96792009-06-13 07:38:31 -04002025 }
2026 }
2027
Andres Moreb902fbf2013-02-25 20:32:51 -05002028 pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Malcolm Priestleyca347592014-03-22 09:01:28 +00002029 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)BytesToWrite);
Forest Bond92b96792009-06-13 07:38:31 -04002030
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002031 pContext->skb = skb;
2032 pContext->type = CONTEXT_DATA_PACKET;
2033 pContext->buf_len = (u16)BytesToWrite + 4 ; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04002034
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01002035 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
Malcolm Priestley81aec602014-02-27 23:06:11 +00002036 &pDevice->sTxEthHeader.h_dest[0],
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01002037 (u16)(BytesToWrite-uHeaderLen),
2038 pTX_Buffer->fifo_head.wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04002039
2040 status = PIPEnsSendBulkOut(pDevice,pContext);
2041
Andres More4e9b5e22013-02-12 20:36:30 -05002042 if (bNeedDeAuth == true) {
Andres More3eaca0d2013-02-25 20:32:52 -05002043 u16 wReason = WLAN_MGMT_REASON_MIC_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -04002044
Andres Moreb902fbf2013-02-25 20:32:51 -05002045 bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (u8 *) &wReason);
Forest Bond92b96792009-06-13 07:38:31 -04002046 }
2047
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002048 if (status != STATUS_PENDING) {
2049 pContext->in_use = false;
2050 dev_kfree_skb_irq(skb);
2051 return STATUS_FAILURE;
2052 }
Forest Bond92b96792009-06-13 07:38:31 -04002053
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002054
2055 return 0;
Forest Bond92b96792009-06-13 07:38:31 -04002056}
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +01002057
2058static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
2059 u8 *key_buffer, struct ieee80211_key_conf *tx_key, struct sk_buff *skb,
2060 u16 payload_len, struct vnt_mic_hdr *mic_hdr)
2061{
2062 struct ieee80211_hdr *hdr = tx_context->hdr;
2063 struct ieee80211_key_seq seq;
2064 u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
2065
2066 /* strip header and icv len from payload */
2067 payload_len -= ieee80211_get_hdrlen_from_skb(skb);
2068 payload_len -= tx_key->icv_len;
2069
2070 switch (tx_key->cipher) {
2071 case WLAN_CIPHER_SUITE_WEP40:
2072 case WLAN_CIPHER_SUITE_WEP104:
2073 memcpy(key_buffer, iv, 3);
2074 memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);
2075
2076 if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
2077 memcpy(key_buffer + 8, iv, 3);
2078 memcpy(key_buffer + 11,
2079 tx_key->key, WLAN_KEY_LEN_WEP40);
2080 }
2081
2082 break;
2083 case WLAN_CIPHER_SUITE_TKIP:
2084 ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);
2085
2086 break;
2087 case WLAN_CIPHER_SUITE_CCMP:
2088
2089 if (!mic_hdr)
2090 return;
2091
2092 mic_hdr->id = 0x59;
2093 mic_hdr->payload_len = cpu_to_be16(payload_len);
2094 memcpy(mic_hdr->mic_addr2, hdr->addr2, ETH_ALEN);
2095
2096 ieee80211_get_key_tx_seq(tx_key, &seq);
2097
2098 mic_hdr->tsc_47_16 = cpu_to_be32((u32)seq.ccmp.pn[3] |
2099 ((u32)seq.ccmp.pn[2] << 8) |
2100 ((u32)seq.ccmp.pn[1] << 16) |
2101 ((u32)seq.ccmp.pn[0] << 24));
2102
2103 mic_hdr->tsc_15_0 = cpu_to_be16((u16)seq.ccmp.pn[5] |
2104 ((u16)seq.ccmp.pn[4] << 8));
2105
2106 if (ieee80211_has_a4(hdr->frame_control))
2107 mic_hdr->hlen = cpu_to_be16(28);
2108 else
2109 mic_hdr->hlen = cpu_to_be16(22);
2110
2111 memcpy(mic_hdr->addr1, hdr->addr1, ETH_ALEN);
2112 memcpy(mic_hdr->addr2, hdr->addr2, ETH_ALEN);
2113 memcpy(mic_hdr->addr3, hdr->addr3, ETH_ALEN);
2114
2115 mic_hdr->frame_control = cpu_to_le16(
2116 le16_to_cpu(hdr->frame_control) & 0xc78f);
2117 mic_hdr->seq_ctrl = cpu_to_le16(
2118 le16_to_cpu(hdr->seq_ctrl) & 0xf);
2119
2120 if (ieee80211_has_a4(hdr->frame_control))
2121 memcpy(mic_hdr->addr4, hdr->addr4, ETH_ALEN);
2122
2123
2124 memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
2125
2126 break;
2127 default:
2128 break;
2129 }
2130
2131}
2132
2133int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
2134{
2135 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2136 struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
2137 struct ieee80211_rate *rate;
2138 struct ieee80211_key_conf *tx_key;
2139 struct ieee80211_hdr *hdr;
2140 struct vnt_mic_hdr *mic_hdr = NULL;
2141 struct vnt_tx_buffer *tx_buffer;
2142 struct vnt_tx_fifo_head *tx_buffer_head;
2143 struct vnt_usb_send_context *tx_context;
2144 unsigned long flags;
2145 u32 frame_size = 0;
2146 u16 tx_bytes, tx_header_size, tx_body_size, current_rate, duration_id;
2147 u8 pkt_type, fb_option = AUTO_FB_NONE;
2148 bool need_rts = false, need_ack = false, is_pspoll = false;
2149 bool need_mic = false;
2150
2151 hdr = (struct ieee80211_hdr *)(skb->data);
2152
2153 rate = ieee80211_get_tx_rate(priv->hw, info);
2154
2155 current_rate = rate->hw_value;
2156 if (priv->wCurrentRate != current_rate) {
2157 priv->wCurrentRate = current_rate;
2158 bScheduleCommand(priv, WLAN_CMD_SETPOWER, NULL);
2159 }
2160
2161 if (current_rate > RATE_11M)
2162 pkt_type = priv->byPacketType;
2163 else
2164 pkt_type = PK_TYPE_11B;
2165
2166 spin_lock_irqsave(&priv->lock, flags);
2167
2168 tx_context = s_vGetFreeContext(priv);
2169 if (!tx_context) {
2170 dev_dbg(&priv->usb->dev, "%s No free context\n", __func__);
2171 spin_unlock_irqrestore(&priv->lock, flags);
2172 return -ENOMEM;
2173 }
2174
2175 tx_context->skb = skb;
2176
2177 spin_unlock_irqrestore(&priv->lock, flags);
2178
2179 tx_buffer = (struct vnt_tx_buffer *)tx_context->data;
2180 tx_buffer_head = &tx_buffer->fifo_head;
2181 tx_body_size = skb->len;
2182
2183 frame_size = tx_body_size + 4;
2184
2185 /* Set time stamp */
2186 tx_buffer_head->time_stamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
2187
2188 /*Set fifo controls */
2189 if (pkt_type == PK_TYPE_11A)
2190 tx_buffer_head->wFIFOCtl = 0;
2191 else if (pkt_type == PK_TYPE_11B)
2192 tx_buffer_head->wFIFOCtl = FIFOCTL_11B;
2193 else if (pkt_type == PK_TYPE_11GB)
2194 tx_buffer_head->wFIFOCtl = FIFOCTL_11GB;
2195 else if (pkt_type == PK_TYPE_11GA)
2196 tx_buffer_head->wFIFOCtl = FIFOCTL_11GA;
2197
2198 if (!ieee80211_is_data(hdr->frame_control)) {
2199 tx_buffer_head->wFIFOCtl |= (FIFOCTL_GENINT |
2200 FIFOCTL_ISDMA0);
2201 tx_buffer_head->wFIFOCtl |= FIFOCTL_TMOEN;
2202
2203 tx_buffer_head->time_stamp =
2204 cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
2205 } else {
2206 tx_buffer_head->time_stamp =
2207 cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
2208 }
2209
2210 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
2211 tx_buffer_head->wFIFOCtl |= FIFOCTL_NEEDACK;
2212 need_ack = true;
2213 }
2214
2215 if (ieee80211_has_retry(hdr->frame_control))
2216 tx_buffer_head->wFIFOCtl |= FIFOCTL_LRETRY;
2217
2218 if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
2219 priv->byPreambleType = PREAMBLE_SHORT;
2220 else
2221 priv->byPreambleType = PREAMBLE_LONG;
2222
2223 if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) {
2224 need_rts = true;
2225 tx_buffer_head->wFIFOCtl |= FIFOCTL_RTS;
2226 }
2227
2228 if (ieee80211_has_a4(hdr->frame_control))
2229 tx_buffer_head->wFIFOCtl |= FIFOCTL_LHEAD;
2230
2231 if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)
2232 is_pspoll = true;
2233
2234 tx_buffer_head->wFragCtl =
2235 cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb)) << 10;
2236
2237 if (info->control.hw_key) {
2238 tx_key = info->control.hw_key;
2239 switch (info->control.hw_key->cipher) {
2240 case WLAN_CIPHER_SUITE_WEP40:
2241 case WLAN_CIPHER_SUITE_WEP104:
2242 tx_buffer_head->wFragCtl |= FRAGCTL_LEGACY;
2243 break;
2244 case WLAN_CIPHER_SUITE_TKIP:
2245 tx_buffer_head->wFragCtl |= FRAGCTL_TKIP;
2246 break;
2247 case WLAN_CIPHER_SUITE_CCMP:
2248 tx_buffer_head->wFragCtl |= FRAGCTL_AES;
2249 need_mic = true;
2250 default:
2251 break;
2252 }
2253 frame_size += tx_key->icv_len;
2254 }
2255
2256 /* legacy rates TODO use ieee80211_tx_rate */
2257 if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
2258 if (priv->byAutoFBCtrl == AUTO_FB_0) {
2259 tx_buffer_head->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
2260
2261 priv->tx_rate_fb0 =
2262 wFB_Opt0[FB_RATE0][current_rate - RATE_18M];
2263 priv->tx_rate_fb1 =
2264 wFB_Opt0[FB_RATE1][current_rate - RATE_18M];
2265
2266 fb_option = AUTO_FB_0;
2267 } else if (priv->byAutoFBCtrl == AUTO_FB_1) {
2268 tx_buffer_head->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
2269
2270 priv->tx_rate_fb0 =
2271 wFB_Opt1[FB_RATE0][current_rate - RATE_18M];
2272 priv->tx_rate_fb1 =
2273 wFB_Opt1[FB_RATE1][current_rate - RATE_18M];
2274
2275 fb_option = AUTO_FB_1;
2276 }
2277 }
2278
2279 duration_id = s_vGenerateTxParameter(tx_context, pkt_type, current_rate,
2280 tx_buffer, &mic_hdr, need_mic, frame_size,
2281 need_ack, NULL, need_rts);
2282
2283 tx_header_size = tx_context->tx_hdr_size;
2284 if (!tx_header_size) {
2285 tx_context->in_use = false;
2286 return -ENOMEM;
2287 }
2288
2289 tx_buffer_head->wFragCtl |= (u16)FRAGCTL_NONFRAG;
2290
2291 tx_bytes = tx_header_size + tx_body_size;
2292
2293 memcpy(tx_context->hdr, skb->data, tx_body_size);
2294
2295 hdr->duration_id = cpu_to_le16(duration_id);
2296
2297 if (info->control.hw_key) {
2298 tx_key = info->control.hw_key;
2299 if (tx_key->keylen > 0)
2300 vnt_fill_txkey(tx_context, tx_buffer_head->tx_key,
2301 tx_key, skb, tx_body_size, mic_hdr);
2302 }
2303
2304 priv->wSeqCounter = (le16_to_cpu(hdr->seq_ctrl) &
2305 IEEE80211_SCTL_SEQ) >> 4;
2306
2307 tx_buffer->tx_byte_count = cpu_to_le16(tx_bytes);
2308 tx_buffer->byPKTNO = (u8)(((current_rate << 4) & 0xf0) |
2309 (priv->wSeqCounter & 0xf));
2310 tx_buffer->byType = 0x00;
2311
2312 tx_bytes += 4;
2313
2314 tx_context->type = CONTEXT_DATA_PACKET;
2315 tx_context->buf_len = tx_bytes;
2316
2317 spin_lock_irqsave(&priv->lock, flags);
2318
2319 if (PIPEnsSendBulkOut(priv, tx_context) != STATUS_PENDING) {
2320 spin_unlock_irqrestore(&priv->lock, flags);
2321 return -EIO;
2322 }
2323
2324 spin_unlock_irqrestore(&priv->lock, flags);
2325
2326 return 0;
2327}
2328
2329static int vnt_beacon_xmit(struct vnt_private *priv,
2330 struct sk_buff *skb)
2331{
2332 struct vnt_beacon_buffer *beacon_buffer;
2333 struct vnt_tx_short_buf_head *short_head;
2334 struct ieee80211_tx_info *info;
2335 struct vnt_usb_send_context *context;
2336 struct ieee80211_mgmt *mgmt_hdr;
2337 unsigned long flags;
2338 u32 frame_size = skb->len + 4;
2339 u16 current_rate, count;
2340
2341 spin_lock_irqsave(&priv->lock, flags);
2342
2343 context = s_vGetFreeContext(priv);
2344 if (!context) {
2345 dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__);
2346 spin_unlock_irqrestore(&priv->lock, flags);
2347 return -ENOMEM;
2348 }
2349
2350 context->skb = skb;
2351
2352 spin_unlock_irqrestore(&priv->lock, flags);
2353
2354 beacon_buffer = (struct vnt_beacon_buffer *)&context->data[0];
2355 short_head = &beacon_buffer->short_head;
2356
2357 if (priv->byBBType == BB_TYPE_11A) {
2358 current_rate = RATE_6M;
2359
2360 /* Get SignalField,ServiceField,Length */
2361 vnt_get_phy_field(priv, frame_size, current_rate,
2362 PK_TYPE_11A, &short_head->ab);
2363
2364 /* Get Duration and TimeStampOff */
2365 short_head->duration = s_uGetDataDuration(priv,
2366 PK_TYPE_11A, false);
2367 short_head->time_stamp_off =
2368 vnt_time_stamp_off(priv, current_rate);
2369 } else {
2370 current_rate = RATE_1M;
2371 short_head->fifo_ctl |= FIFOCTL_11B;
2372
2373 /* Get SignalField,ServiceField,Length */
2374 vnt_get_phy_field(priv, frame_size, current_rate,
2375 PK_TYPE_11B, &short_head->ab);
2376
2377 /* Get Duration and TimeStampOff */
2378 short_head->duration = s_uGetDataDuration(priv,
2379 PK_TYPE_11B, false);
2380 short_head->time_stamp_off =
2381 vnt_time_stamp_off(priv, current_rate);
2382 }
2383
2384 /* Generate Beacon Header */
2385 mgmt_hdr = &beacon_buffer->mgmt_hdr;
2386 memcpy(mgmt_hdr, skb->data, skb->len);
2387
2388 /* time stamp always 0 */
2389 mgmt_hdr->u.beacon.timestamp = 0;
2390
2391 info = IEEE80211_SKB_CB(skb);
2392 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
2393 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
2394 hdr->duration_id = 0;
2395 hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4);
2396 }
2397
2398 priv->wSeqCounter++;
2399 if (priv->wSeqCounter > 0x0fff)
2400 priv->wSeqCounter = 0;
2401
2402 count = sizeof(struct vnt_tx_short_buf_head) + skb->len;
2403
2404 beacon_buffer->tx_byte_count = cpu_to_le16(count);
2405 beacon_buffer->byPKTNO = (u8)(((current_rate << 4) & 0xf0) |
2406 ((priv->wSeqCounter - 1) & 0x000f));
2407 beacon_buffer->byType = 0x01;
2408
2409 context->type = CONTEXT_BEACON_PACKET;
2410 context->buf_len = count + 4; /* USB header */
2411
2412 spin_lock_irqsave(&priv->lock, flags);
2413
2414 if (PIPEnsSendBulkOut(priv, context) != STATUS_PENDING)
2415 ieee80211_free_txskb(priv->hw, context->skb);
2416
2417 spin_unlock_irqrestore(&priv->lock, flags);
2418
2419 return 0;
2420}
2421
2422int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
2423{
2424 struct sk_buff *beacon;
2425
2426 beacon = ieee80211_beacon_get(priv->hw, vif);
2427 if (!beacon)
2428 return -ENOMEM;
2429
2430 if (vnt_beacon_xmit(priv, beacon)) {
2431 ieee80211_free_txskb(priv->hw, beacon);
2432 return -ENODEV;
2433 }
2434
2435 return 0;
2436}
2437
2438int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
2439 struct ieee80211_bss_conf *conf)
2440{
2441 int ret;
2442
2443 vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
2444
2445 vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
2446
2447 vnt_mac_set_beacon_interval(priv, conf->beacon_int);
2448
2449 vnt_clear_current_tsf(priv);
2450
2451 vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
2452
2453 vnt_reset_next_tbtt(priv, conf->beacon_int);
2454
2455 ret = vnt_beacon_make(priv, vif);
2456
2457 return ret;
2458}