blob: 9604b8ec6fc8e36caabf458b8ca5aab75a0c398d [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 Priestley3fd56202014-01-08 20:08:42 +0000347 data_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
348 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)
351 ack_time = BBuGetFrameTime(priv->byPreambleType, pkt_type, 14,
352 (u16)priv->byTopCCKBasicRate);
353 else
354 ack_time = BBuGetFrameTime(priv->byPreambleType, pkt_type, 14,
355 (u16)priv->byTopOFDMBasicRate);
356
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 Priestley342e2e22014-01-08 20:13:29 +0000378 data_time = BBuGetFrameTime(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) {
382 rts_time = BBuGetFrameTime(priv->byPreambleType,
383 pkt_type, 20, priv->byTopCCKBasicRate);
384 cts_time = ack_time = BBuGetFrameTime(priv->byPreambleType,
385 pkt_type, 14, priv->byTopCCKBasicRate);
386 } else if (rsv_type == 1) {
387 rts_time = BBuGetFrameTime(priv->byPreambleType,
388 pkt_type, 20, priv->byTopCCKBasicRate);
389 cts_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
390 14, priv->byTopCCKBasicRate);
391 ack_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
392 14, priv->byTopOFDMBasicRate);
393 } else if (rsv_type == 2) {
394 rts_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
395 20, priv->byTopOFDMBasicRate);
396 cts_time = ack_time = BBuGetFrameTime(priv->byPreambleType,
397 pkt_type, 14, priv->byTopOFDMBasicRate);
398 } else if (rsv_type == 3) {
399 cts_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
400 14, priv->byTopCCKBasicRate);
401 ack_time = BBuGetFrameTime(priv->byPreambleType, pkt_type,
402 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 Priestleyb02ccd52013-08-13 19:59:31 +0100422 uAckTime = BBuGetFrameTime(pDevice->byPreambleType,
423 byPktType, 14, pDevice->byTopCCKBasicRate);
424 else
425 uAckTime = BBuGetFrameTime(pDevice->byPreambleType,
426 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:
445 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType,
446 14, pDevice->byTopCCKBasicRate);
447 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:
455 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType,
456 14, pDevice->byTopOFDMBasicRate);
457 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 Priestley5e67ee42013-08-26 11:04:50 +0100581static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
582 struct ieee80211_rts *rts, struct ethhdr *eth_hdr,
Malcolm Priestley10bb39a2014-03-18 19:25:01 +0000583 __le16 duration)
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100584{
585 rts->duration = duration;
Malcolm Priestleyf4554d32014-03-22 09:01:31 +0000586 rts->frame_control =
587 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100588
Malcolm Priestleya0ad2772014-02-15 21:56:20 +0000589 if (priv->op_mode == NL80211_IFTYPE_ADHOC ||
590 priv->op_mode == NL80211_IFTYPE_AP)
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100591 memcpy(rts->ra, eth_hdr->h_dest, ETH_ALEN);
592 else
593 memcpy(rts->ra, priv->abyBSSID, ETH_ALEN);
594
Malcolm Priestleya0ad2772014-02-15 21:56:20 +0000595 if (priv->op_mode == NL80211_IFTYPE_AP)
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100596 memcpy(rts->ta, priv->abyBSSID, ETH_ALEN);
597 else
598 memcpy(rts->ta, eth_hdr->h_source, ETH_ALEN);
599
600 return 0;
601}
602
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100603static u16 vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100604 struct vnt_rts_g *buf, struct ethhdr *eth_hdr,
605 u8 pkt_type, u32 frame_len, int need_ack,
606 u16 current_rate, u8 fb_option)
607{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100608 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100609 u16 rts_frame_len = 20;
610
Malcolm Priestley205056f2014-06-04 18:25:34 +0100611 vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100612 PK_TYPE_11B, &buf->b);
Malcolm Priestley205056f2014-06-04 18:25:34 +0100613 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100614 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
615
Malcolm Priestley4e011172014-03-18 19:24:55 +0000616 buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100617 PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000618 buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100619 pkt_type, current_rate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000620 buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100621 pkt_type, current_rate, need_ack, fb_option);
622
Malcolm Priestley4e011172014-03-18 19:24:55 +0000623 vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->duration_aa);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100624
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100625 return vnt_rxtx_datahead_g(tx_context, pkt_type, current_rate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100626 &buf->data_head, frame_len, need_ack);
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100627}
628
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100629static u16 vnt_rxtx_rts_g_fb_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100630 struct vnt_rts_g_fb *buf, struct ethhdr *eth_hdr,
631 u8 pkt_type, u32 frame_len, int need_ack,
632 u16 current_rate, u8 fb_option)
633{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100634 struct vnt_private *priv = tx_context->priv;
Malcolm Priestleyec917132013-08-26 11:07:46 +0100635 u16 rts_frame_len = 20;
636
Malcolm Priestley205056f2014-06-04 18:25:34 +0100637 vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100638 PK_TYPE_11B, &buf->b);
Malcolm Priestley205056f2014-06-04 18:25:34 +0100639 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100640 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
641
642
Malcolm Priestley4e011172014-03-18 19:24:55 +0000643 buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100644 PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000645 buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100646 pkt_type, current_rate, need_ack, fb_option);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000647 buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
Malcolm Priestleyec917132013-08-26 11:07:46 +0100648 pkt_type, current_rate, need_ack, fb_option);
649
650
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000651 buf->rts_duration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100652 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000653 buf->rts_duration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100654 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000655 buf->rts_duration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100656 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000657 buf->rts_duration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100658 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100659
Malcolm Priestley4e011172014-03-18 19:24:55 +0000660 vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->duration_aa);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100661
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100662 return vnt_rxtx_datahead_g_fb(tx_context, pkt_type, current_rate,
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100663 &buf->data_head, frame_len, need_ack);
Malcolm Priestleyec917132013-08-26 11:07:46 +0100664}
665
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100666static u16 vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley17126332013-08-26 11:09:38 +0100667 struct vnt_rts_ab *buf, struct ethhdr *eth_hdr,
668 u8 pkt_type, u32 frame_len, int need_ack,
669 u16 current_rate, u8 fb_option)
670{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100671 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley17126332013-08-26 11:09:38 +0100672 u16 rts_frame_len = 20;
673
Malcolm Priestley205056f2014-06-04 18:25:34 +0100674 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley17126332013-08-26 11:09:38 +0100675 priv->byTopOFDMBasicRate, pkt_type, &buf->ab);
676
Malcolm Priestley4e011172014-03-18 19:24:55 +0000677 buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley17126332013-08-26 11:09:38 +0100678 pkt_type, current_rate, need_ack, fb_option);
679
Malcolm Priestley4e011172014-03-18 19:24:55 +0000680 vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->duration);
Malcolm Priestley17126332013-08-26 11:09:38 +0100681
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100682 return vnt_rxtx_datahead_ab(tx_context, pkt_type, current_rate,
Malcolm Priestley5634a5a2013-10-01 16:00:20 +0100683 &buf->data_head, frame_len, need_ack);
Malcolm Priestley17126332013-08-26 11:09:38 +0100684}
685
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100686static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100687 struct vnt_rts_a_fb *buf, struct ethhdr *eth_hdr,
688 u8 pkt_type, u32 frame_len, int need_ack,
689 u16 current_rate, u8 fb_option)
690{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100691 struct vnt_private *priv = tx_context->priv;
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100692 u16 rts_frame_len = 20;
693
Malcolm Priestley205056f2014-06-04 18:25:34 +0100694 vnt_get_phy_field(priv, rts_frame_len,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100695 priv->byTopOFDMBasicRate, pkt_type, &buf->a);
696
Malcolm Priestley4e011172014-03-18 19:24:55 +0000697 buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100698 pkt_type, current_rate, need_ack, fb_option);
699
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000700 buf->rts_duration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100701 frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100702
Malcolm Priestleyfadc3bd2014-03-18 19:24:56 +0000703 buf->rts_duration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100704 frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100705
Malcolm Priestley4e011172014-03-18 19:24:55 +0000706 vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->duration);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100707
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100708 return vnt_rxtx_datahead_a_fb(tx_context, pkt_type, current_rate,
Malcolm Priestleybd3f51f2013-10-01 15:56:48 +0100709 &buf->data_head, frame_len, need_ack);
Malcolm Priestley9d2578c2013-08-26 11:12:00 +0100710}
711
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100712static u16 s_vFillRTSHead(struct vnt_usb_send_context *tx_context, u8 byPktType,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100713 union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
Andres Moreceb8c5d2013-03-18 20:33:49 -0500714 struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
Forest Bond92b96792009-06-13 07:38:31 -0400715{
Forest Bond92b96792009-06-13 07:38:31 -0400716
Malcolm Priestley13fe62a2013-08-26 11:17:52 +0100717 if (!head)
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100718 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400719
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100720 /* Note: So far RTSHead doesn't appear in ATIM
721 * & Beacom DMA, so we don't need to take them
722 * into account.
723 * Otherwise, we need to modified codes for them.
724 */
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100725 switch (byPktType) {
726 case PK_TYPE_11GB:
727 case PK_TYPE_11GA:
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100728 if (byFBOption == AUTO_FB_NONE)
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100729 return vnt_rxtx_rts_g_head(tx_context, &head->rts_g,
Malcolm Priestley5e67ee42013-08-26 11:04:50 +0100730 psEthHeader, byPktType, cbFrameLength,
731 bNeedAck, wCurrentRate, byFBOption);
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100732 else
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100733 return vnt_rxtx_rts_g_fb_head(tx_context,
734 &head->rts_g_fb, psEthHeader, byPktType,
735 cbFrameLength, bNeedAck, wCurrentRate,
736 byFBOption);
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100737 break;
738 case PK_TYPE_11A:
Malcolm Priestley2b83ebd2013-08-27 09:58:21 +0100739 if (byFBOption) {
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100740 return vnt_rxtx_rts_a_fb_head(tx_context,
741 &head->rts_a_fb, psEthHeader, byPktType,
742 cbFrameLength, bNeedAck, wCurrentRate,
743 byFBOption);
Malcolm Priestley2b83ebd2013-08-27 09:58:21 +0100744 break;
745 }
Malcolm Priestley0bddd302013-08-27 09:56:50 +0100746 case PK_TYPE_11B:
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100747 return vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab,
Malcolm Priestley17126332013-08-26 11:09:38 +0100748 psEthHeader, byPktType, cbFrameLength,
749 bNeedAck, wCurrentRate, byFBOption);
Malcolm Priestley9d5829b2013-08-26 11:21:11 +0100750 }
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100751
752 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400753}
754
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100755static u16 s_vFillCTSHead(struct vnt_usb_send_context *tx_context,
Malcolm Priestley5fb8e412013-08-27 12:07:58 +0100756 u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
757 int bNeedAck, u16 wCurrentRate, u8 byFBOption)
Forest Bond92b96792009-06-13 07:38:31 -0400758{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100759 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000760 u32 uCTSFrameLen = 14;
Forest Bond92b96792009-06-13 07:38:31 -0400761
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100762 if (!head)
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100763 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400764
Malcolm Priestleyc921cc82013-08-20 20:47:49 +0100765 if (byFBOption != AUTO_FB_NONE) {
766 /* Auto Fall back */
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100767 struct vnt_cts_fb *pBuf = &head->cts_g_fb;
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100768 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100769 vnt_get_phy_field(pDevice, uCTSFrameLen,
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100770 pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
Malcolm Priestley4e011172014-03-18 19:24:55 +0000771 pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100772 cbFrameLength, byPktType,
773 wCurrentRate, bNeedAck, byFBOption);
774 /* Get CTSDuration_ba_f0 */
Malcolm Priestley7fd57472014-03-18 19:24:59 +0000775 pBuf->cts_duration_ba_f0 = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100776 CTSDUR_BA_F0, cbFrameLength, byPktType,
777 pDevice->tx_rate_fb0, bNeedAck, byFBOption);
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100778 /* Get CTSDuration_ba_f1 */
Malcolm Priestley7fd57472014-03-18 19:24:59 +0000779 pBuf->cts_duration_ba_f1 = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +0100780 CTSDUR_BA_F1, cbFrameLength, byPktType,
781 pDevice->tx_rate_fb1, bNeedAck, byFBOption);
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100782 /* Get CTS Frame body */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000783 pBuf->data.duration = pBuf->duration_ba;
Malcolm Priestleyd9560ae2014-03-22 09:01:32 +0000784 pBuf->data.frame_control =
785 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
786
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100787 memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
Malcolm Priestley5b852f52013-10-01 15:54:56 +0100788
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100789 return vnt_rxtx_datahead_g_fb(tx_context, byPktType,
790 wCurrentRate, &pBuf->data_head, cbFrameLength,
791 bNeedAck);
Malcolm Priestleyc921cc82013-08-20 20:47:49 +0100792 } else {
Malcolm Priestley27df3eb2013-08-27 11:48:34 +0100793 struct vnt_cts *pBuf = &head->cts_g;
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100794 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +0100795 vnt_get_phy_field(pDevice, uCTSFrameLen,
Malcolm Priestleyaed387c2013-08-20 22:52:30 +0100796 pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100797 /* Get CTSDuration_ba */
Malcolm Priestley4e011172014-03-18 19:24:55 +0000798 pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice,
Malcolm Priestleye34f9db2013-08-13 20:17:11 +0100799 CTSDUR_BA, cbFrameLength, byPktType,
800 wCurrentRate, bNeedAck, byFBOption);
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100801 /*Get CTS Frame body*/
Malcolm Priestley4e011172014-03-18 19:24:55 +0000802 pBuf->data.duration = pBuf->duration_ba;
Malcolm Priestleyd9560ae2014-03-22 09:01:32 +0000803 pBuf->data.frame_control =
804 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
805
Malcolm Priestley14840cd2013-08-05 22:12:42 +0100806 memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100807
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100808 return vnt_rxtx_datahead_g(tx_context, byPktType, wCurrentRate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +0100809 &pBuf->data_head, cbFrameLength, bNeedAck);
Forest Bond92b96792009-06-13 07:38:31 -0400810 }
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100811
812 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400813}
814
Forest Bond92b96792009-06-13 07:38:31 -0400815/*+
816 *
817 * Description:
818 * Generate FIFO control for MAC & Baseband controller
819 *
820 * Parameters:
821 * In:
822 * pDevice - Pointer to adpater
823 * pTxDataHead - Transmit Data Buffer
824 * pTxBufHead - pTxBufHead
825 * pvRrvTime - pvRrvTime
826 * pvRTS - RTS Buffer
827 * pCTS - CTS Buffer
828 * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS)
829 * bNeedACK - If need ACK
Forest Bond92b96792009-06-13 07:38:31 -0400830 * Out:
831 * none
832 *
833 * Return Value: none
834 *
835-*/
Andres Morecc856e62010-05-17 21:34:01 -0300836
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100837static u16 s_vGenerateTxParameter(struct vnt_usb_send_context *tx_context,
Malcolm Priestley8e344c82013-09-17 19:58:11 +0100838 u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
Malcolm Priestleyfa575602013-09-26 19:00:41 +0100839 struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
Malcolm Priestley05cc6172014-04-30 21:31:12 +0100840 int bNeedACK, struct ethhdr *psEthHeader, bool need_rts)
Forest Bond92b96792009-06-13 07:38:31 -0400841{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100842 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestley8e344c82013-09-17 19:58:11 +0100843 struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100844 union vnt_tx_data_head *head = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000845 u16 wFifoCtl;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +0000846 u8 byFBOption = AUTO_FB_NONE;
Forest Bond92b96792009-06-13 07:38:31 -0400847
Malcolm Priestley03a9cf32014-03-22 09:01:30 +0000848 pFifoHead->current_rate = cpu_to_le16(wCurrentRate);
Malcolm Priestley92928f12013-10-07 20:14:01 +0100849 wFifoCtl = pFifoHead->wFIFOCtl;
Forest Bond92b96792009-06-13 07:38:31 -0400850
Malcolm Priestley92928f12013-10-07 20:14:01 +0100851 if (wFifoCtl & FIFOCTL_AUTO_FB_0)
852 byFBOption = AUTO_FB_0;
853 else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
854 byFBOption = AUTO_FB_1;
Forest Bond92b96792009-06-13 07:38:31 -0400855
Malcolm Priestley92928f12013-10-07 20:14:01 +0100856 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
857 if (need_rts) {
858 struct vnt_rrv_time_rts *pBuf =
859 &tx_buffer->tx_head.tx_rts.rts;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100860
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000861 pBuf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100862 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000863 pBuf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 1,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100864 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000865 pBuf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(pDevice, 0,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100866 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100867
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000868 pBuf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100869 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000870 pBuf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100871 PK_TYPE_11B, cbFrameSize,
872 pDevice->byTopCCKBasicRate, bNeedACK);
873
874 if (need_mic) {
875 *mic_hdr = &tx_buffer->
876 tx_head.tx_rts.tx.mic.hdr;
877 head = &tx_buffer->tx_head.tx_rts.tx.mic.head;
878 } else {
879 head = &tx_buffer->tx_head.tx_rts.tx.head;
880 }
881
882 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100883 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100884 cbFrameSize, bNeedACK, psEthHeader,
885 wCurrentRate, byFBOption);
886
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100887 } else {
Malcolm Priestley92928f12013-10-07 20:14:01 +0100888 struct vnt_rrv_time_cts *pBuf = &tx_buffer->
889 tx_head.tx_cts.cts;
890
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000891 pBuf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100892 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000893 pBuf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100894 PK_TYPE_11B, cbFrameSize,
895 pDevice->byTopCCKBasicRate, bNeedACK);
896
Malcolm Priestley372108e2014-03-18 19:25:00 +0000897 pBuf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100898 byPktType, cbFrameSize, wCurrentRate);
899
900 if (need_mic) {
901 *mic_hdr = &tx_buffer->
902 tx_head.tx_cts.tx.mic.hdr;
903 head = &tx_buffer->tx_head.tx_cts.tx.mic.head;
904 } else {
905 head = &tx_buffer->tx_head.tx_cts.tx.head;
906 }
907
908 /* Fill CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100909 return s_vFillCTSHead(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100910 head, cbFrameSize, bNeedACK, wCurrentRate,
911 byFBOption);
912 }
913 } else if (byPktType == PK_TYPE_11A) {
914 if (need_mic) {
915 *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
916 head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
917 } else {
918 head = &tx_buffer->tx_head.tx_ab.tx.head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100919 }
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100920
Malcolm Priestley92928f12013-10-07 20:14:01 +0100921 if (need_rts) {
922 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
923 tx_head.tx_ab.ab;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100924
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000925 pBuf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100926 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100927
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000928 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100929 byPktType, cbFrameSize, wCurrentRate, bNeedACK);
930
931 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100932 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100933 cbFrameSize, bNeedACK, psEthHeader,
934 wCurrentRate, byFBOption);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100935 } else {
Malcolm Priestley92928f12013-10-07 20:14:01 +0100936 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
937 tx_head.tx_ab.ab;
938
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000939 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100940 PK_TYPE_11A, cbFrameSize,
941 wCurrentRate, bNeedACK);
942
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100943 return vnt_rxtx_datahead_a_fb(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100944 wCurrentRate, &head->data_head_a_fb,
945 cbFrameSize, bNeedACK);
946 }
947 } else if (byPktType == PK_TYPE_11B) {
948 if (need_mic) {
949 *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
950 head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
951 } else {
952 head = &tx_buffer->tx_head.tx_ab.tx.head;
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100953 }
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +0100954
Malcolm Priestley92928f12013-10-07 20:14:01 +0100955 if (need_rts) {
956 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
957 tx_head.tx_ab.ab;
Malcolm Priestleya90186e2013-10-01 15:58:54 +0100958
Malcolm Priestley85417bf2014-03-18 19:24:57 +0000959 pBuf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0,
Malcolm Priestleycfabe4b2013-08-22 21:03:40 +0100960 byPktType, cbFrameSize, wCurrentRate);
Malcolm Priestleyb9cc2fc2013-09-26 18:57:34 +0100961
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000962 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100963 PK_TYPE_11B, cbFrameSize, wCurrentRate,
964 bNeedACK);
965
966 /* Fill RTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100967 return s_vFillRTSHead(tx_context, byPktType, head,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100968 cbFrameSize,
Malcolm Priestley351c7dc2013-08-27 12:02:54 +0100969 bNeedACK, psEthHeader, wCurrentRate, byFBOption);
Malcolm Priestley92928f12013-10-07 20:14:01 +0100970 } else {
971 struct vnt_rrv_time_ab *pBuf = &tx_buffer->
972 tx_head.tx_ab.ab;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +0100973
Malcolm Priestley5ff627a2014-03-18 19:24:58 +0000974 pBuf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100975 PK_TYPE_11B, cbFrameSize,
976 wCurrentRate, bNeedACK);
Malcolm Priestleya90186e2013-10-01 15:58:54 +0100977
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100978 return vnt_rxtx_datahead_ab(tx_context, byPktType,
Malcolm Priestley92928f12013-10-07 20:14:01 +0100979 wCurrentRate, &head->data_head_ab,
980 cbFrameSize, bNeedACK);
981 }
Malcolm Priestleyc12dca02013-10-01 16:03:40 +0100982 }
983
Malcolm Priestley0a0f4b62013-10-01 15:50:24 +0100984 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400985}
986/*
Andres Moreb902fbf2013-02-25 20:32:51 -0500987 u8 * pbyBuffer,//point to pTxBufHead
Andres More3eaca0d2013-02-25 20:32:52 -0500988 u16 wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
Andres Morecc856e62010-05-17 21:34:01 -0300989 unsigned int cbFragmentSize,//Hdr+payoad+FCS
Forest Bond92b96792009-06-13 07:38:31 -0400990*/
991
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100992static int s_bPacketToWirelessUsb(struct vnt_usb_send_context *tx_context,
993 u8 byPktType, struct vnt_tx_buffer *tx_buffer, int bNeedEncryption,
Malcolm Priestley05cc6172014-04-30 21:31:12 +0100994 u32 uSkbPacketLen, struct ethhdr *psEthHeader,
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +0100995 u8 *pPacket, PSKeyItem pTransmitKey, u32 uNodeIndex, u16 wCurrentRate,
996 u32 *pcbHeaderLen, u32 *pcbTotalLen)
Forest Bond92b96792009-06-13 07:38:31 -0400997{
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +0100998 struct vnt_private *pDevice = tx_context->priv;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +0100999 struct vnt_tx_fifo_head *pTxBufHead = &tx_buffer->fifo_head;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001000 u32 cbFrameSize, cbFrameBodySize;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001001 u32 cb802_1_H_len;
1002 u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbMACHdLen = 0;
1003 u32 cbFCSlen = 4, cbMICHDR = 0;
Malcolm Priestleyf46142b2013-08-27 11:56:33 +01001004 int bNeedACK;
1005 bool bRTS = false;
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001006 u8 *pbyType, *pbyMacHdr, *pbyIVHead, *pbyPayloadHead;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001007 u8 abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
1008 u8 abySNAP_Bridgetunnel[ETH_ALEN]
1009 = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
1010 u32 uDuration;
1011 u32 cbHeaderLength = 0, uPadding = 0;
Malcolm Priestley5a5d6a82013-08-23 14:33:55 +01001012 struct vnt_mic_hdr *pMICHDR;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001013 u8 byFBOption = AUTO_FB_NONE, byFragType;
Malcolm Priestley4235f722013-08-24 12:42:01 +01001014 u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001015 u32 *pdwMIC_L, *pdwMIC_R;
Andres Moree269fc22013-02-12 20:36:29 -05001016 int bSoftWEP = false;
Malcolm Priestley9e38a5c2013-09-26 18:47:25 +01001017
Malcolm Priestleyc545e6a2013-10-01 16:07:25 +01001018 pMICHDR = NULL;
Forest Bond92b96792009-06-13 07:38:31 -04001019
Malcolm Priestleye2efba72012-11-11 15:20:52 +00001020 if (bNeedEncryption && pTransmitKey->pvKeyTable) {
Andres More4e9b5e22013-02-12 20:36:30 -05001021 if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
1022 bSoftWEP = true; /* WEP 256 */
Malcolm Priestleye2efba72012-11-11 15:20:52 +00001023 }
Forest Bond92b96792009-06-13 07:38:31 -04001024
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001025 /* Get pkt type */
1026 if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN)
1027 cb802_1_H_len = 8;
1028 else
1029 cb802_1_H_len = 0;
Forest Bond92b96792009-06-13 07:38:31 -04001030
Charles Clément21ec51f2010-05-18 10:08:14 -07001031 cbFrameBodySize = uSkbPacketLen - ETH_HLEN + cb802_1_H_len;
Forest Bond92b96792009-06-13 07:38:31 -04001032
1033 //Set packet type
Andres More3eaca0d2013-02-25 20:32:52 -05001034 pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8);
Forest Bond92b96792009-06-13 07:38:31 -04001035
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001036 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC ||
1037 pDevice->op_mode == NL80211_IFTYPE_AP) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001038 if (is_multicast_ether_addr(psEthHeader->h_dest)) {
Andres Moree269fc22013-02-12 20:36:29 -05001039 bNeedACK = false;
Andres More22040bb2010-08-02 20:21:44 -03001040 pTxBufHead->wFIFOCtl =
1041 pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
1042 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001043 bNeedACK = true;
Andres More22040bb2010-08-02 20:21:44 -03001044 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1045 }
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001046 } else {
1047 /* MSDUs in Infra mode always need ACK */
1048 bNeedACK = true;
1049 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1050 }
Forest Bond92b96792009-06-13 07:38:31 -04001051
Malcolm Priestley58462512014-03-22 09:01:27 +00001052 pTxBufHead->time_stamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
Forest Bond92b96792009-06-13 07:38:31 -04001053
Forest Bond92b96792009-06-13 07:38:31 -04001054 //Set FRAGCTL_MACHDCNT
Malcolm Priestley078d0cf2013-11-25 22:14:16 +00001055 cbMACHdLen = WLAN_HDR_ADDR3_LEN;
1056
Andres More3eaca0d2013-02-25 20:32:52 -05001057 pTxBufHead->wFragCtl |= (u16)(cbMACHdLen << 10);
Forest Bond92b96792009-06-13 07:38:31 -04001058
1059 //Set FIFOCTL_GrpAckPolicy
Andres More4e9b5e22013-02-12 20:36:30 -05001060 if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
Forest Bond92b96792009-06-13 07:38:31 -04001061 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK;
1062 }
1063
Malcolm Priestleyf84cdf62013-10-15 21:00:09 +01001064 /* Set Auto Fallback Ctl */
1065 if (wCurrentRate >= RATE_18M) {
1066 if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
1067 pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
1068
1069 pDevice->tx_rate_fb0 =
1070 wFB_Opt0[FB_RATE0][wCurrentRate - RATE_18M];
1071 pDevice->tx_rate_fb1 =
1072 wFB_Opt0[FB_RATE1][wCurrentRate - RATE_18M];
1073
1074 byFBOption = AUTO_FB_0;
1075 } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
1076 pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
1077 pDevice->tx_rate_fb0 =
1078 wFB_Opt1[FB_RATE0][wCurrentRate - RATE_18M];
1079 pDevice->tx_rate_fb1 =
1080 wFB_Opt1[FB_RATE1][wCurrentRate - RATE_18M];
1081
1082 byFBOption = AUTO_FB_1;
1083 }
1084 }
Forest Bond92b96792009-06-13 07:38:31 -04001085
Andres More4e9b5e22013-02-12 20:36:30 -05001086 if (bSoftWEP != true) {
Forest Bond92b96792009-06-13 07:38:31 -04001087 if ((bNeedEncryption) && (pTransmitKey != NULL)) { //WEP enabled
1088 if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104
1089 pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
1090 }
1091 if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
1092 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Tx Set wFragCtl == FRAGCTL_TKIP\n");
1093 pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
1094 }
1095 else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP
1096 pTxBufHead->wFragCtl |= FRAGCTL_AES;
1097 }
1098 }
1099 }
1100
Forest Bond92b96792009-06-13 07:38:31 -04001101 if ((bNeedEncryption) && (pTransmitKey != NULL)) {
1102 if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
1103 cbIVlen = 4;
1104 cbICVlen = 4;
1105 }
1106 else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
1107 cbIVlen = 8;//IV+ExtIV
1108 cbMIClen = 8;
1109 cbICVlen = 4;
1110 }
1111 if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
1112 cbIVlen = 8;//RSN Header
1113 cbICVlen = 8;//MIC
Malcolm Priestley5a5d6a82013-08-23 14:33:55 +01001114 cbMICHDR = sizeof(struct vnt_mic_hdr);
Forest Bond92b96792009-06-13 07:38:31 -04001115 }
Andres Moree269fc22013-02-12 20:36:29 -05001116 if (bSoftWEP == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001117 //MAC Header should be padding 0 to DW alignment.
1118 uPadding = 4 - (cbMACHdLen%4);
1119 uPadding %= 4;
1120 }
1121 }
1122
1123 cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
1124
Andres Moree269fc22013-02-12 20:36:29 -05001125 if ( (bNeedACK == false) ||(cbFrameSize < pDevice->wRTSThreshold) ) {
1126 bRTS = false;
Forest Bond92b96792009-06-13 07:38:31 -04001127 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001128 bRTS = true;
Forest Bond92b96792009-06-13 07:38:31 -04001129 pTxBufHead->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY);
1130 }
1131
Forest Bond92b96792009-06-13 07:38:31 -04001132 //=========================
1133 // No Fragmentation
1134 //=========================
1135 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n");
1136 byFragType = FRAGCTL_NONFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001137 //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
1138
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001139 /* Fill FIFO, RrvTime, RTS and CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01001140 uDuration = s_vGenerateTxParameter(tx_context, byPktType, wCurrentRate,
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001141 tx_buffer, &pMICHDR, cbMICHDR,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001142 cbFrameSize, bNeedACK, psEthHeader, bRTS);
Malcolm Priestleyc12dca02013-10-01 16:03:40 +01001143
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001144 cbHeaderLength = tx_context->tx_hdr_size;
1145 if (!cbHeaderLength)
1146 return false;
1147
1148 pbyMacHdr = (u8 *)tx_context->hdr;
1149 pbyIVHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding);
1150 pbyPayloadHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
1151
1152 /* Generate TX MAC Header */
1153 s_vGenerateMACHeader(pDevice, tx_context->hdr, (u16)uDuration,
1154 psEthHeader, bNeedEncryption, byFragType, 0);
Forest Bond92b96792009-06-13 07:38:31 -04001155
Andres More4e9b5e22013-02-12 20:36:30 -05001156 if (bNeedEncryption == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001157 //Fill TXKEY
Malcolm Priestley3695c462014-05-31 13:34:59 +01001158 s_vFillTxKey(tx_context, pTxBufHead, pbyIVHead, pTransmitKey,
1159 (u16)cbFrameBodySize, pMICHDR);
Forest Bond92b96792009-06-13 07:38:31 -04001160 }
1161
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001162 /* 802.1H */
1163 if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001164 if ((psEthHeader->h_proto == cpu_to_be16(ETH_P_IPX)) ||
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001165 (psEthHeader->h_proto == cpu_to_le16(0xF380)))
Andres Moreb902fbf2013-02-25 20:32:51 -05001166 memcpy((u8 *) (pbyPayloadHead),
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001167 abySNAP_Bridgetunnel, 6);
1168 else
1169 memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6);
Forest Bond92b96792009-06-13 07:38:31 -04001170
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001171 pbyType = (u8 *) (pbyPayloadHead + 6);
Forest Bond92b96792009-06-13 07:38:31 -04001172
Malcolm Priestleyc47b0a32013-11-24 11:51:49 +00001173 memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16));
1174 }
Forest Bond92b96792009-06-13 07:38:31 -04001175
Forest Bond92b96792009-06-13 07:38:31 -04001176 if (pPacket != NULL) {
1177 // Copy the Packet into a tx Buffer
Jim Lieb3e362592009-08-12 14:54:11 -07001178 memcpy((pbyPayloadHead + cb802_1_H_len),
Charles Clément21ec51f2010-05-18 10:08:14 -07001179 (pPacket + ETH_HLEN),
1180 uSkbPacketLen - ETH_HLEN
Forest Bond92b96792009-06-13 07:38:31 -04001181 );
1182
1183 } else {
1184 // while bRelayPacketSend psEthHeader is point to header+payload
Andres Moreb902fbf2013-02-25 20:32:51 -05001185 memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN);
Forest Bond92b96792009-06-13 07:38:31 -04001186 }
1187
Andres More4e9b5e22013-02-12 20:36:30 -05001188 if ((bNeedEncryption == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
Forest Bond92b96792009-06-13 07:38:31 -04001189
1190 ///////////////////////////////////////////////////////////////////
1191
Malcolm Priestley14c5ef52013-01-17 23:19:37 +00001192 if (pDevice->vnt_mgmt.eAuthenMode == WMAC_AUTH_WPANONE) {
1193 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
1194 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
1195 }
Forest Bond92b96792009-06-13 07:38:31 -04001196 else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) {
Andres More52a7e642013-02-25 20:32:53 -05001197 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
1198 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
Forest Bond92b96792009-06-13 07:38:31 -04001199 }
1200 else {
Andres More52a7e642013-02-25 20:32:53 -05001201 dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[24]);
1202 dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[28]);
Forest Bond92b96792009-06-13 07:38:31 -04001203 }
1204 // DO Software Michael
1205 MIC_vInit(dwMICKey0, dwMICKey1);
Andres Moreceb8c5d2013-03-18 20:33:49 -05001206 MIC_vAppend((u8 *)&(psEthHeader->h_dest[0]), 12);
Forest Bond92b96792009-06-13 07:38:31 -04001207 dwMIC_Priority = 0;
Andres Moreb902fbf2013-02-25 20:32:51 -05001208 MIC_vAppend((u8 *)&dwMIC_Priority, 4);
Malcolm Priestleyb4dc03a2012-11-11 15:45:52 +00001209 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n",
1210 dwMICKey0, dwMICKey1);
Forest Bond92b96792009-06-13 07:38:31 -04001211
1212 ///////////////////////////////////////////////////////////////////
1213
1214 //DBG_PRN_GRP12(("Length:%d, %d\n", cbFrameBodySize, uFromHDtoPLDLength));
1215 //for (ii = 0; ii < cbFrameBodySize; ii++) {
Andres Moreb902fbf2013-02-25 20:32:51 -05001216 // DBG_PRN_GRP12(("%02x ", *((u8 *)((pbyPayloadHead + cb802_1_H_len) + ii))));
Forest Bond92b96792009-06-13 07:38:31 -04001217 //}
1218 //DBG_PRN_GRP12(("\n\n\n"));
1219
1220 MIC_vAppend(pbyPayloadHead, cbFrameBodySize);
1221
Andres More52a7e642013-02-25 20:32:53 -05001222 pdwMIC_L = (u32 *)(pbyPayloadHead + cbFrameBodySize);
1223 pdwMIC_R = (u32 *)(pbyPayloadHead + cbFrameBodySize + 4);
Forest Bond92b96792009-06-13 07:38:31 -04001224
1225 MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
1226 MIC_vUnInit();
1227
Andres More4e9b5e22013-02-12 20:36:30 -05001228 if (pDevice->bTxMICFail == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001229 *pdwMIC_L = 0;
1230 *pdwMIC_R = 0;
Andres Moree269fc22013-02-12 20:36:29 -05001231 pDevice->bTxMICFail = false;
Forest Bond92b96792009-06-13 07:38:31 -04001232 }
1233 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize);
1234 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen);
1235 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
1236 }
1237
Andres More4e9b5e22013-02-12 20:36:30 -05001238 if (bSoftWEP == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001239
Andres More3eaca0d2013-02-25 20:32:52 -05001240 s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (u16)(cbFrameBodySize + cbMIClen));
Forest Bond92b96792009-06-13 07:38:31 -04001241
Andres More4e9b5e22013-02-12 20:36:30 -05001242 } else if ( ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) && (bNeedEncryption == true)) ||
1243 ((pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) && (bNeedEncryption == true)) ||
1244 ((pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) && (bNeedEncryption == true)) ) {
Forest Bond92b96792009-06-13 07:38:31 -04001245 cbFrameSize -= cbICVlen;
1246 }
1247
Forest Bond92b96792009-06-13 07:38:31 -04001248 cbFrameSize -= cbFCSlen;
Forest Bond92b96792009-06-13 07:38:31 -04001249
1250 *pcbHeaderLen = cbHeaderLength;
1251 *pcbTotalLen = cbHeaderLength + cbFrameSize ;
1252
Forest Bond92b96792009-06-13 07:38:31 -04001253 //Set FragCtl in TxBufferHead
Andres More3eaca0d2013-02-25 20:32:52 -05001254 pTxBufHead->wFragCtl |= (u16)byFragType;
Forest Bond92b96792009-06-13 07:38:31 -04001255
Andres More4e9b5e22013-02-12 20:36:30 -05001256 return true;
Forest Bond92b96792009-06-13 07:38:31 -04001257
1258}
1259
Forest Bond92b96792009-06-13 07:38:31 -04001260/*+
1261 *
1262 * Description:
1263 * Translate 802.3 to 802.11 header
1264 *
1265 * Parameters:
1266 * In:
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001267 * pDevice - Pointer to adapter
Forest Bond92b96792009-06-13 07:38:31 -04001268 * dwTxBufferAddr - Transmit Buffer
1269 * pPacket - Packet from upper layer
1270 * cbPacketSize - Transmit Data Length
1271 * Out:
1272 * pcbHeadSize - Header size of MAC&Baseband control and 802.11 Header
1273 * pcbAppendPayload - size of append payload for 802.1H translation
1274 *
1275 * Return Value: none
1276 *
1277-*/
1278
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001279static void s_vGenerateMACHeader(struct vnt_private *pDevice,
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001280 struct ieee80211_hdr *pMACHeader, u16 wDuration,
1281 struct ethhdr *psEthHeader, int bNeedEncrypt, u16 wFragType,
1282 u32 uFragIdx)
Forest Bond92b96792009-06-13 07:38:31 -04001283{
Forest Bond92b96792009-06-13 07:38:31 -04001284
Malcolm Priestleyc921cc82013-08-20 20:47:49 +01001285 pMACHeader->frame_control = TYPE_802_11_DATA;
Forest Bond92b96792009-06-13 07:38:31 -04001286
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001287 if (pDevice->op_mode == NL80211_IFTYPE_AP) {
Andres More1cac4a42013-03-18 20:33:50 -05001288 memcpy(&(pMACHeader->addr1[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001289 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001290 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001291 memcpy(&(pMACHeader->addr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
1292 memcpy(&(pMACHeader->addr3[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001293 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001294 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001295 pMACHeader->frame_control |= FC_FROMDS;
Andres More9a0e7562010-04-13 21:54:48 -03001296 } else {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001297 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
Andres More1cac4a42013-03-18 20:33:50 -05001298 memcpy(&(pMACHeader->addr1[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001299 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001300 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001301 memcpy(&(pMACHeader->addr2[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001302 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001303 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001304 memcpy(&(pMACHeader->addr3[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001305 &(pDevice->abyBSSID[0]),
1306 ETH_ALEN);
1307 } else {
Andres More1cac4a42013-03-18 20:33:50 -05001308 memcpy(&(pMACHeader->addr3[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001309 &(psEthHeader->h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001310 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001311 memcpy(&(pMACHeader->addr2[0]),
Andres Moreceb8c5d2013-03-18 20:33:49 -05001312 &(psEthHeader->h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001313 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001314 memcpy(&(pMACHeader->addr1[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001315 &(pDevice->abyBSSID[0]),
1316 ETH_ALEN);
Andres More1cac4a42013-03-18 20:33:50 -05001317 pMACHeader->frame_control |= FC_TODS;
Forest Bond92b96792009-06-13 07:38:31 -04001318 }
1319 }
1320
1321 if (bNeedEncrypt)
Andres More1cac4a42013-03-18 20:33:50 -05001322 pMACHeader->frame_control |= cpu_to_le16((u16)WLAN_SET_FC_ISWEP(1));
Forest Bond92b96792009-06-13 07:38:31 -04001323
Andres More1cac4a42013-03-18 20:33:50 -05001324 pMACHeader->duration_id = cpu_to_le16(wDuration);
Forest Bond92b96792009-06-13 07:38:31 -04001325
Andres More1cac4a42013-03-18 20:33:50 -05001326 pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
Forest Bond92b96792009-06-13 07:38:31 -04001327
1328 //Set FragNumber in Sequence Control
Andres More1cac4a42013-03-18 20:33:50 -05001329 pMACHeader->seq_ctrl |= cpu_to_le16((u16)uFragIdx);
Forest Bond92b96792009-06-13 07:38:31 -04001330
1331 if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
1332 pDevice->wSeqCounter++;
1333 if (pDevice->wSeqCounter > 0x0fff)
1334 pDevice->wSeqCounter = 0;
1335 }
1336
1337 if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag
Andres More1cac4a42013-03-18 20:33:50 -05001338 pMACHeader->frame_control |= FC_MOREFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001339 }
1340}
1341
Forest Bond92b96792009-06-13 07:38:31 -04001342/*+
1343 *
1344 * Description:
1345 * Request instructs a MAC to transmit a 802.11 management packet through
1346 * the adapter onto the medium.
1347 *
1348 * Parameters:
1349 * In:
1350 * hDeviceContext - Pointer to the adapter
1351 * pPacket - A pointer to a descriptor for the packet to transmit
1352 * Out:
1353 * none
1354 *
Andres Moree269fc22013-02-12 20:36:29 -05001355 * Return Value: CMD_STATUS_PENDING if MAC Tx resource available; otherwise false
Forest Bond92b96792009-06-13 07:38:31 -04001356 *
1357-*/
1358
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001359CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
1360 struct vnt_tx_mgmt *pPacket)
Forest Bond92b96792009-06-13 07:38:31 -04001361{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001362 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
Malcolm Priestleyf39c0d82013-08-15 19:34:37 +01001363 struct vnt_tx_buffer *pTX_Buffer;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001364 struct vnt_usb_send_context *pContext;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001365 struct vnt_tx_fifo_head *pTxBufHead;
Andres More1cac4a42013-03-18 20:33:50 -05001366 struct ieee80211_hdr *pMACHeader;
Andres Moreceb8c5d2013-03-18 20:33:49 -05001367 struct ethhdr sEthHeader;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001368 u8 byPktType, *pbyTxBufferAddr;
Malcolm Priestleyf0e0d502013-09-26 18:52:10 +01001369 struct vnt_mic_hdr *pMICHDR = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001370 u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
Andres Moree269fc22013-02-12 20:36:29 -05001371 int bNeedACK, bIsPSPOLL = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001372 u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
1373 u32 uPadding = 0;
1374 u16 wTxBufSize;
1375 u32 cbMacHdLen;
1376 u16 wCurrentRate = RATE_1M;
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001377 unsigned long flags;
1378
1379 if (pDevice->byBBType == BB_TYPE_11A) {
1380 wCurrentRate = RATE_6M;
1381 byPktType = PK_TYPE_11A;
1382 } else {
1383 wCurrentRate = RATE_1M;
1384 byPktType = PK_TYPE_11B;
1385 }
1386
1387 if (pMgmt->eScanState != WMAC_NO_SCANNING)
Malcolm Priestley4f5290e2014-05-27 21:05:21 +01001388 vnt_rf_setpower(pDevice, wCurrentRate, pDevice->byCurrentCh);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001389 else
Malcolm Priestley4f5290e2014-05-27 21:05:21 +01001390 vnt_rf_setpower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001391
1392 pDevice->wCurrentRate = wCurrentRate;
1393
1394 spin_lock_irqsave(&pDevice->lock, flags);
Forest Bond92b96792009-06-13 07:38:31 -04001395
Malcolm Priestleyaceaf012013-11-26 19:06:35 +00001396 pContext = s_vGetFreeContext(pDevice);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001397 if (!pContext) {
1398 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
1399 "ManagementSend TX...NO CONTEXT!\n");
1400 spin_unlock_irqrestore(&pDevice->lock, flags);
1401 return CMD_STATUS_RESOURCES;
1402 }
Forest Bond92b96792009-06-13 07:38:31 -04001403
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001404 pTX_Buffer = (struct vnt_tx_buffer *)&pContext->data[0];
Forest Bond92b96792009-06-13 07:38:31 -04001405 cbFrameBodySize = pPacket->cbPayloadLen;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001406 pTxBufHead = &pTX_Buffer->fifo_head;
Malcolm Priestleyab51f512014-05-31 13:35:00 +01001407 pbyTxBufferAddr = (u8 *)pTxBufHead;
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001408 wTxBufSize = sizeof(struct vnt_tx_fifo_head);
Forest Bond92b96792009-06-13 07:38:31 -04001409
Forest Bond92b96792009-06-13 07:38:31 -04001410
Forest Bond92b96792009-06-13 07:38:31 -04001411 //Set packet type
1412 if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
1413 pTxBufHead->wFIFOCtl = 0;
1414 }
1415 else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
1416 pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
1417 }
1418 else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
1419 pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
1420 }
1421 else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
1422 pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
1423 }
1424
1425 pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
Malcolm Priestley58462512014-03-22 09:01:27 +00001426 pTxBufHead->time_stamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
Forest Bond92b96792009-06-13 07:38:31 -04001427
Andres More22040bb2010-08-02 20:21:44 -03001428 if (is_multicast_ether_addr(pPacket->p80211Header->sA3.abyAddr1)) {
Andres Moree269fc22013-02-12 20:36:29 -05001429 bNeedACK = false;
Forest Bond92b96792009-06-13 07:38:31 -04001430 }
1431 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001432 bNeedACK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001433 pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
1434 };
1435
1436 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
1437 (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) {
1438
1439 pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
1440 //Set Preamble type always long
1441 //pDevice->byPreambleType = PREAMBLE_LONG;
1442 // probe-response don't retry
1443 //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) {
Andres Moree269fc22013-02-12 20:36:29 -05001444 // bNeedACK = false;
Forest Bond92b96792009-06-13 07:38:31 -04001445 // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK);
1446 //}
1447 }
1448
1449 pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
1450
1451 if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
Andres More4e9b5e22013-02-12 20:36:30 -05001452 bIsPSPOLL = true;
Forest Bond92b96792009-06-13 07:38:31 -04001453 cbMacHdLen = WLAN_HDR_ADDR2_LEN;
1454 } else {
1455 cbMacHdLen = WLAN_HDR_ADDR3_LEN;
1456 }
1457
1458 //Set FRAGCTL_MACHDCNT
Andres More3eaca0d2013-02-25 20:32:52 -05001459 pTxBufHead->wFragCtl |= cpu_to_le16((u16)(cbMacHdLen << 10));
Forest Bond92b96792009-06-13 07:38:31 -04001460
1461 // Notes:
1462 // Although spec says MMPDU can be fragmented; In most case,
1463 // no one will send a MMPDU under fragmentation. With RTS may occur.
Forest Bond92b96792009-06-13 07:38:31 -04001464
1465 if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
1466 if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
1467 cbIVlen = 4;
1468 cbICVlen = 4;
1469 pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
1470 }
1471 else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
1472 cbIVlen = 8;//IV+ExtIV
1473 cbMIClen = 8;
1474 cbICVlen = 4;
1475 pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
1476 //We need to get seed here for filling TxKey entry.
1477 //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
1478 // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
1479 }
1480 else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
1481 cbIVlen = 8;//RSN Header
1482 cbICVlen = 8;//MIC
1483 pTxBufHead->wFragCtl |= FRAGCTL_AES;
Forest Bond92b96792009-06-13 07:38:31 -04001484 }
1485 //MAC Header should be padding 0 to DW alignment.
1486 uPadding = 4 - (cbMacHdLen%4);
1487 uPadding %= 4;
1488 }
1489
1490 cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen;
1491
1492 //Set FIFOCTL_GrpAckPolicy
Andres More4e9b5e22013-02-12 20:36:30 -05001493 if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
Forest Bond92b96792009-06-13 07:38:31 -04001494 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK;
1495 }
1496 //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
1497
Andres Moreceb8c5d2013-03-18 20:33:49 -05001498 memcpy(&(sEthHeader.h_dest[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001499 &(pPacket->p80211Header->sA3.abyAddr1[0]),
1500 ETH_ALEN);
Andres Moreceb8c5d2013-03-18 20:33:49 -05001501 memcpy(&(sEthHeader.h_source[0]),
Andres More9a0e7562010-04-13 21:54:48 -03001502 &(pPacket->p80211Header->sA3.abyAddr2[0]),
1503 ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -04001504 //=========================
1505 // No Fragmentation
1506 //=========================
Andres More3eaca0d2013-02-25 20:32:52 -05001507 pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
Forest Bond92b96792009-06-13 07:38:31 -04001508
Malcolm Priestley351c7dc2013-08-27 12:02:54 +01001509 /* Fill FIFO,RrvTime,RTS,and CTS */
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01001510 uDuration = s_vGenerateTxParameter(pContext, byPktType, wCurrentRate,
Malcolm Priestleyfa575602013-09-26 19:00:41 +01001511 pTX_Buffer, &pMICHDR, 0,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001512 cbFrameSize, bNeedACK, &sEthHeader, false);
Forest Bond92b96792009-06-13 07:38:31 -04001513
Malcolm Priestley1622c8f2014-05-31 13:34:58 +01001514 cbHeaderSize = pContext->tx_hdr_size;
1515 if (!cbHeaderSize) {
1516 pContext->in_use = false;
1517 return CMD_STATUS_RESOURCES;
1518 }
1519
1520 pMACHeader = pContext->hdr;
Forest Bond92b96792009-06-13 07:38:31 -04001521
1522 cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
1523
1524 if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
Andres Moreb902fbf2013-02-25 20:32:51 -05001525 u8 * pbyIVHead;
1526 u8 * pbyPayloadHead;
1527 u8 * pbyBSSID;
Forest Bond92b96792009-06-13 07:38:31 -04001528 PSKeyItem pTransmitKey = NULL;
1529
Andres Moreb902fbf2013-02-25 20:32:51 -05001530 pbyIVHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
1531 pbyPayloadHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
Forest Bond92b96792009-06-13 07:38:31 -04001532 do {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001533 if (pDevice->op_mode == NL80211_IFTYPE_STATION &&
1534 pDevice->bLinkPass == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001535 pbyBSSID = pDevice->abyBSSID;
1536 // get pairwise key
Andres Moree269fc22013-02-12 20:36:29 -05001537 if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001538 // get group key
Andres More4e9b5e22013-02-12 20:36:30 -05001539 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001540 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
1541 break;
1542 }
1543 } else {
1544 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n");
1545 break;
1546 }
1547 }
1548 // get group key
1549 pbyBSSID = pDevice->abyBroadcastAddr;
Andres Moree269fc22013-02-12 20:36:29 -05001550 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001551 pTransmitKey = NULL;
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001552 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->op_mode);
Forest Bond92b96792009-06-13 07:38:31 -04001553 } else {
1554 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
1555 }
Andres Moree269fc22013-02-12 20:36:29 -05001556 } while(false);
Forest Bond92b96792009-06-13 07:38:31 -04001557 //Fill TXKEY
Malcolm Priestley3695c462014-05-31 13:34:59 +01001558 s_vFillTxKey(pContext, pTxBufHead, pbyIVHead, pTransmitKey,
1559 (u16)cbFrameBodySize, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001560
Jim Lieb3e362592009-08-12 14:54:11 -07001561 memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
Andres Moreb902fbf2013-02-25 20:32:51 -05001562 memcpy(pbyPayloadHead, ((u8 *)(pPacket->p80211Header) + cbMacHdLen),
Forest Bond92b96792009-06-13 07:38:31 -04001563 cbFrameBodySize);
1564 }
1565 else {
1566 // Copy the Packet into a tx Buffer
Jim Lieb3e362592009-08-12 14:54:11 -07001567 memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
Forest Bond92b96792009-06-13 07:38:31 -04001568 }
1569
Andres More1cac4a42013-03-18 20:33:50 -05001570 pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
Forest Bond92b96792009-06-13 07:38:31 -04001571 pDevice->wSeqCounter++ ;
1572 if (pDevice->wSeqCounter > 0x0fff)
1573 pDevice->wSeqCounter = 0;
1574
1575 if (bIsPSPOLL) {
1576 // The MAC will automatically replace the Duration-field of MAC header by Duration-field
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001577 // of FIFO control header.
Forest Bond92b96792009-06-13 07:38:31 -04001578 // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is
1579 // in the same place of other packet's Duration-field).
1580 // And it will cause Cisco-AP to issue Disassociation-packet
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001581 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
Malcolm Priestley78363fd2013-10-01 15:52:16 +01001582 struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
1583 tx_cts.tx.head.cts_g.data_head;
Malcolm Priestley4e011172014-03-18 19:24:55 +00001584 data_head->duration_a =
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001585 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
Malcolm Priestley4e011172014-03-18 19:24:55 +00001586 data_head->duration_b =
Malcolm Priestley7e60a3de2013-08-16 23:48:03 +01001587 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
1588 } else {
Malcolm Priestleyc12dca02013-10-01 16:03:40 +01001589 struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
1590 tx_ab.tx.head.data_head_ab;
Malcolm Priestley4e011172014-03-18 19:24:55 +00001591 data_head->duration =
Malcolm Priestley558becf2013-08-16 23:50:32 +01001592 cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
1593 }
Forest Bond92b96792009-06-13 07:38:31 -04001594 }
1595
Malcolm Priestleyca347592014-03-22 09:01:28 +00001596 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)(cbReqCount));
Andres Moreb902fbf2013-02-25 20:32:51 -05001597 pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Forest Bond92b96792009-06-13 07:38:31 -04001598 pTX_Buffer->byType = 0x00;
1599
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001600 pContext->skb = NULL;
1601 pContext->type = CONTEXT_MGMT_PACKET;
1602 pContext->buf_len = (u16)cbReqCount + 4; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04001603
Andres More1cac4a42013-03-18 20:33:50 -05001604 if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001605 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
1606 &pMACHeader->addr1[0], (u16)cbFrameSize,
1607 pTxBufHead->wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04001608 }
1609 else {
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01001610 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
1611 &pMACHeader->addr3[0], (u16)cbFrameSize,
1612 pTxBufHead->wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04001613 }
1614
1615 PIPEnsSendBulkOut(pDevice,pContext);
Malcolm Priestley931cb9f2014-05-15 22:49:15 +01001616
1617 spin_unlock_irqrestore(&pDevice->lock, flags);
1618
Forest Bond92b96792009-06-13 07:38:31 -04001619 return CMD_STATUS_PENDING;
1620}
1621
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001622CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
1623 struct vnt_tx_mgmt *pPacket)
Forest Bond92b96792009-06-13 07:38:31 -04001624{
Malcolm Priestley01f865b2013-08-15 19:40:08 +01001625 struct vnt_beacon_buffer *pTX_Buffer;
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001626 struct vnt_tx_short_buf_head *short_head;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001627 u32 cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN;
1628 u32 cbHeaderSize = 0;
Andres More1cac4a42013-03-18 20:33:50 -05001629 struct ieee80211_hdr *pMACHeader;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001630 u16 wCurrentRate;
1631 u32 cbFrameBodySize;
1632 u32 cbReqCount;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001633 struct vnt_usb_send_context *pContext;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001634 CMD_STATUS status;
Forest Bond92b96792009-06-13 07:38:31 -04001635
Malcolm Priestleyaceaf012013-11-26 19:06:35 +00001636 pContext = s_vGetFreeContext(pDevice);
Forest Bond92b96792009-06-13 07:38:31 -04001637 if (NULL == pContext) {
1638 status = CMD_STATUS_RESOURCES;
1639 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n");
1640 return status ;
1641 }
Malcolm Priestley01f865b2013-08-15 19:40:08 +01001642
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001643 pTX_Buffer = (struct vnt_beacon_buffer *)&pContext->data[0];
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001644 short_head = &pTX_Buffer->short_head;
Forest Bond92b96792009-06-13 07:38:31 -04001645
1646 cbFrameBodySize = pPacket->cbPayloadLen;
1647
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001648 cbHeaderSize = sizeof(struct vnt_tx_short_buf_head);
Forest Bond92b96792009-06-13 07:38:31 -04001649
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001650 if (pDevice->byBBType == BB_TYPE_11A) {
1651 wCurrentRate = RATE_6M;
1652
1653 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +01001654 vnt_get_phy_field(pDevice, cbFrameSize, wCurrentRate,
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001655 PK_TYPE_11A, &short_head->ab);
1656
1657 /* Get Duration and TimeStampOff */
1658 short_head->duration = s_uGetDataDuration(pDevice,
1659 PK_TYPE_11A, false);
1660 short_head->time_stamp_off =
1661 vnt_time_stamp_off(pDevice, wCurrentRate);
1662 } else {
1663 wCurrentRate = RATE_1M;
1664 short_head->fifo_ctl |= FIFOCTL_11B;
1665
1666 /* Get SignalField,ServiceField,Length */
Malcolm Priestley205056f2014-06-04 18:25:34 +01001667 vnt_get_phy_field(pDevice, cbFrameSize, wCurrentRate,
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001668 PK_TYPE_11B, &short_head->ab);
1669
1670 /* Get Duration and TimeStampOff */
1671 short_head->duration = s_uGetDataDuration(pDevice,
Malcolm Priestley6b5ad9d2013-08-21 22:16:04 +01001672 PK_TYPE_11B, false);
Malcolm Priestleyc7c57b22013-11-24 13:25:25 +00001673 short_head->time_stamp_off =
1674 vnt_time_stamp_off(pDevice, wCurrentRate);
1675 }
1676
Forest Bond92b96792009-06-13 07:38:31 -04001677
Malcolm Priestley0b71fe32013-11-24 13:27:32 +00001678 /* Generate Beacon Header */
1679 pMACHeader = &pTX_Buffer->hdr;
Forest Bond92b96792009-06-13 07:38:31 -04001680
Malcolm Priestley0b71fe32013-11-24 13:27:32 +00001681 memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
1682
1683 pMACHeader->duration_id = 0;
1684 pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
1685 pDevice->wSeqCounter++;
1686 if (pDevice->wSeqCounter > 0x0fff)
1687 pDevice->wSeqCounter = 0;
Forest Bond92b96792009-06-13 07:38:31 -04001688
1689 cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize;
1690
Malcolm Priestleyfad8e4a2014-03-22 09:01:29 +00001691 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)cbReqCount);
Andres Moreb902fbf2013-02-25 20:32:51 -05001692 pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Forest Bond92b96792009-06-13 07:38:31 -04001693 pTX_Buffer->byType = 0x01;
1694
Malcolm Priestley30a05b32014-05-15 22:49:11 +01001695 pContext->skb = NULL;
1696 pContext->type = CONTEXT_MGMT_PACKET;
1697 pContext->buf_len = (u16)cbReqCount + 4; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04001698
1699 PIPEnsSendBulkOut(pDevice,pContext);
1700 return CMD_STATUS_PENDING;
1701
1702}
1703
Forest Bond92b96792009-06-13 07:38:31 -04001704//TYPE_AC0DMA data tx
1705/*
1706 * Description:
1707 * Tx packet via AC0DMA(DMA1)
1708 *
1709 * Parameters:
1710 * In:
1711 * pDevice - Pointer to the adapter
1712 * skb - Pointer to tx skb packet
1713 * Out:
1714 * void
1715 *
1716 * Return Value: NULL
1717 */
1718
Malcolm Priestley05cc6172014-04-30 21:31:12 +01001719int nsDMA_tx_packet(struct vnt_private *pDevice, struct sk_buff *skb)
Forest Bond92b96792009-06-13 07:38:31 -04001720{
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001721 struct net_device_stats *pStats = &pDevice->stats;
1722 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
Malcolm Priestleyf39c0d82013-08-15 19:34:37 +01001723 struct vnt_tx_buffer *pTX_Buffer;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001724 u32 BytesToWrite = 0, uHeaderLen = 0;
1725 u32 uNodeIndex = 0;
1726 u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
1727 u16 wAID;
1728 u8 byPktType;
Andres Moree269fc22013-02-12 20:36:29 -05001729 int bNeedEncryption = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001730 PSKeyItem pTransmitKey = NULL;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001731 int ii;
Andres Moree269fc22013-02-12 20:36:29 -05001732 int bTKIP_UseGTK = false;
1733 int bNeedDeAuth = false;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001734 u8 *pbyBSSID;
Andres Moree269fc22013-02-12 20:36:29 -05001735 int bNodeExist = false;
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +01001736 struct vnt_usb_send_context *pContext;
Andres Moredfdcc422013-02-12 20:36:28 -05001737 bool fConvertedPacket;
Malcolm Priestleyd56131d2013-01-17 23:15:22 +00001738 u32 status;
1739 u16 wKeepRate = pDevice->wCurrentRate;
Andres Moree269fc22013-02-12 20:36:29 -05001740 int bTxeapol_key = false;
Forest Bond92b96792009-06-13 07:38:31 -04001741
Forest Bond92b96792009-06-13 07:38:31 -04001742 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
1743
1744 if (pDevice->uAssocCount == 0) {
1745 dev_kfree_skb_irq(skb);
1746 return 0;
1747 }
1748
Andres Moreb902fbf2013-02-25 20:32:51 -05001749 if (is_multicast_ether_addr((u8 *)(skb->data))) {
Forest Bond92b96792009-06-13 07:38:31 -04001750 uNodeIndex = 0;
Andres More4e9b5e22013-02-12 20:36:30 -05001751 bNodeExist = true;
Forest Bond92b96792009-06-13 07:38:31 -04001752 if (pMgmt->sNodeDBTable[0].bPSEnable) {
1753
1754 skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
1755 pMgmt->sNodeDBTable[0].wEnQueueCnt++;
1756 // set tx map
1757 pMgmt->abyPSTxMap[0] |= byMask[0];
1758 return 0;
1759 }
Masanari Iida93184692012-08-13 21:21:50 +09001760 // multicast/broadcast data rate
Forest Bond92b96792009-06-13 07:38:31 -04001761
1762 if (pDevice->byBBType != BB_TYPE_11A)
1763 pDevice->wCurrentRate = RATE_2M;
1764 else
1765 pDevice->wCurrentRate = RATE_24M;
1766 // long preamble type
1767 pDevice->byPreambleType = PREAMBLE_SHORT;
1768
1769 }else {
1770
Andres Moreb902fbf2013-02-25 20:32:51 -05001771 if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data), &uNodeIndex)) {
Forest Bond92b96792009-06-13 07:38:31 -04001772
1773 if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
1774
1775 skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
1776
1777 pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
1778 // set tx map
1779 wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
1780 pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7];
1781 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
1782 (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
1783
1784 return 0;
1785 }
1786 // AP rate decided from node
1787 pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
1788 // tx preamble decided from node
1789
1790 if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
1791 pDevice->byPreambleType = pDevice->byShortPreamble;
1792
1793 }else {
1794 pDevice->byPreambleType = PREAMBLE_LONG;
1795 }
Andres More4e9b5e22013-02-12 20:36:30 -05001796 bNodeExist = true;
Forest Bond92b96792009-06-13 07:38:31 -04001797 }
1798 }
1799
Andres Moree269fc22013-02-12 20:36:29 -05001800 if (bNodeExist == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001801 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n");
1802 dev_kfree_skb_irq(skb);
1803 return 0;
1804 }
1805 }
1806
Tobias Klauser838c2d62014-04-25 11:53:58 +02001807 memcpy(&pDevice->sTxEthHeader, skb->data, ETH_HLEN);
Forest Bond92b96792009-06-13 07:38:31 -04001808
1809//mike add:station mode check eapol-key challenge--->
1810{
Andres Moreb902fbf2013-02-25 20:32:51 -05001811 u8 Protocol_Version; //802.1x Authentication
1812 u8 Packet_Type; //802.1x Authentication
1813 u8 Descriptor_type;
Andres More3eaca0d2013-02-25 20:32:52 -05001814 u16 Key_info;
Forest Bond92b96792009-06-13 07:38:31 -04001815
Charles Clément21ec51f2010-05-18 10:08:14 -07001816 Protocol_Version = skb->data[ETH_HLEN];
1817 Packet_Type = skb->data[ETH_HLEN+1];
1818 Descriptor_type = skb->data[ETH_HLEN+1+1+2];
1819 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 -05001820 if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001821 /* 802.1x OR eapol-key challenge frame transfer */
1822 if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
1823 (Packet_Type == 3)) {
Andres More4e9b5e22013-02-12 20:36:30 -05001824 bTxeapol_key = true;
Forest Bond92b96792009-06-13 07:38:31 -04001825 if(!(Key_info & BIT3) && //WPA or RSN group-key challenge
1826 (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key
1827 if(Descriptor_type==254) {
Andres More4e9b5e22013-02-12 20:36:30 -05001828 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001829 PRINT_K("WPA ");
1830 }
1831 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001832 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001833 PRINT_K("WPA2(re-keying) ");
1834 }
1835 PRINT_K("Authentication completed!!\n");
1836 }
Justin P. Mattocka0a1f612012-08-26 08:16:43 -07001837 else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairwise-key challenge
Forest Bond92b96792009-06-13 07:38:31 -04001838 (Key_info & BIT8) && (Key_info & BIT9)) {
Andres More4e9b5e22013-02-12 20:36:30 -05001839 pDevice->fWPA_Authened = true;
Forest Bond92b96792009-06-13 07:38:31 -04001840 PRINT_K("WPA2 Authentication completed!!\n");
1841 }
1842 }
1843 }
1844}
1845//mike add:station mode check eapol-key challenge<---
1846
Andres More4e9b5e22013-02-12 20:36:30 -05001847 if (pDevice->bEncryptionEnable == true) {
1848 bNeedEncryption = true;
Forest Bond92b96792009-06-13 07:38:31 -04001849 // get Transmit key
1850 do {
1851 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
1852 (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
1853 pbyBSSID = pDevice->abyBSSID;
1854 // get pairwise key
Andres Moree269fc22013-02-12 20:36:29 -05001855 if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001856 // get group key
Andres More4e9b5e22013-02-12 20:36:30 -05001857 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
1858 bTKIP_UseGTK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001859 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
1860 break;
1861 }
1862 } else {
1863 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n");
1864 break;
1865 }
1866 }else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001867 /* TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 */
1868 pbyBSSID = pDevice->sTxEthHeader.h_dest;
Forest Bond92b96792009-06-13 07:38:31 -04001869 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n");
1870 for (ii = 0; ii< 6; ii++)
1871 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii));
1872 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n");
1873
1874 // get pairwise key
Andres More4e9b5e22013-02-12 20:36:30 -05001875 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
Forest Bond92b96792009-06-13 07:38:31 -04001876 break;
1877 }
1878 // get group key
1879 pbyBSSID = pDevice->abyBroadcastAddr;
Andres Moree269fc22013-02-12 20:36:29 -05001880 if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001881 pTransmitKey = NULL;
1882 if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
1883 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode);
1884 }
1885 else
1886 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode);
1887 } else {
Andres More4e9b5e22013-02-12 20:36:30 -05001888 bTKIP_UseGTK = true;
Forest Bond92b96792009-06-13 07:38:31 -04001889 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
1890 }
Andres Moree269fc22013-02-12 20:36:29 -05001891 } while(false);
Forest Bond92b96792009-06-13 07:38:31 -04001892 }
1893
Andres Moreb902fbf2013-02-25 20:32:51 -05001894 byPktType = (u8)pDevice->byPacketType;
Forest Bond92b96792009-06-13 07:38:31 -04001895
1896 if (pDevice->bFixRate) {
1897 if (pDevice->byBBType == BB_TYPE_11B) {
1898 if (pDevice->uConnectionRate >= RATE_11M) {
1899 pDevice->wCurrentRate = RATE_11M;
1900 } else {
Andres More3eaca0d2013-02-25 20:32:52 -05001901 pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
Forest Bond92b96792009-06-13 07:38:31 -04001902 }
1903 } else {
1904 if ((pDevice->byBBType == BB_TYPE_11A) &&
1905 (pDevice->uConnectionRate <= RATE_6M)) {
1906 pDevice->wCurrentRate = RATE_6M;
1907 } else {
1908 if (pDevice->uConnectionRate >= RATE_54M)
1909 pDevice->wCurrentRate = RATE_54M;
1910 else
Andres More3eaca0d2013-02-25 20:32:52 -05001911 pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
Forest Bond92b96792009-06-13 07:38:31 -04001912 }
1913 }
1914 }
1915 else {
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001916 if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
Forest Bond92b96792009-06-13 07:38:31 -04001917 // Adhoc Tx rate decided from node DB
Andres Moreceb8c5d2013-03-18 20:33:49 -05001918 if (is_multicast_ether_addr(pDevice->sTxEthHeader.h_dest)) {
Forest Bond92b96792009-06-13 07:38:31 -04001919 // Multicast use highest data rate
1920 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
1921 // preamble type
1922 pDevice->byPreambleType = pDevice->byShortPreamble;
1923 }
1924 else {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001925 if (BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.h_dest[0]), &uNodeIndex)) {
Forest Bond92b96792009-06-13 07:38:31 -04001926 pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
1927 if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
1928 pDevice->byPreambleType = pDevice->byShortPreamble;
1929
1930 }
1931 else {
1932 pDevice->byPreambleType = PREAMBLE_LONG;
1933 }
1934 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Found Node Index is [%d] Tx Data Rate:[%d]\n",uNodeIndex, pDevice->wCurrentRate);
1935 }
1936 else {
1937 if (pDevice->byBBType != BB_TYPE_11A)
1938 pDevice->wCurrentRate = RATE_2M;
1939 else
1940 pDevice->wCurrentRate = RATE_24M; // refer to vMgrCreateOwnIBSS()'s
1941 // abyCurrExtSuppRates[]
1942 pDevice->byPreambleType = PREAMBLE_SHORT;
1943 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Not Found Node use highest basic Rate.....\n");
1944 }
1945 }
1946 }
Malcolm Priestleya0ad2772014-02-15 21:56:20 +00001947 if (pDevice->op_mode == NL80211_IFTYPE_STATION) {
Forest Bond92b96792009-06-13 07:38:31 -04001948 // Infra STA rate decided from AP Node, index = 0
1949 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
1950 }
1951 }
1952
Andres Moreceb8c5d2013-03-18 20:33:49 -05001953 if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001954 if (pDevice->byBBType != BB_TYPE_11A) {
1955 pDevice->wCurrentRate = RATE_1M;
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001956 pDevice->byTopCCKBasicRate = RATE_1M;
1957 pDevice->byTopOFDMBasicRate = RATE_6M;
1958 } else {
1959 pDevice->wCurrentRate = RATE_6M;
Malcolm Priestleyaa209ee2012-08-29 23:08:21 +01001960 pDevice->byTopCCKBasicRate = RATE_1M;
1961 pDevice->byTopOFDMBasicRate = RATE_6M;
1962 }
1963 }
Forest Bond92b96792009-06-13 07:38:31 -04001964
Andres More0cbd8d92010-05-06 20:34:29 -03001965 DBG_PRT(MSG_LEVEL_DEBUG,
1966 KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n",
1967 pDevice->wCurrentRate);
Forest Bond92b96792009-06-13 07:38:31 -04001968
1969 if (wKeepRate != pDevice->wCurrentRate) {
Andres More0cbd8d92010-05-06 20:34:29 -03001970 bScheduleCommand((void *) pDevice, WLAN_CMD_SETPOWER, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001971 }
1972
1973 if (pDevice->wCurrentRate <= RATE_11M) {
1974 byPktType = PK_TYPE_11B;
1975 }
1976
Andres More4e9b5e22013-02-12 20:36:30 -05001977 if (bNeedEncryption == true) {
Andres Moreceb8c5d2013-03-18 20:33:49 -05001978 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.h_proto));
1979 if ((pDevice->sTxEthHeader.h_proto) == cpu_to_be16(ETH_P_PAE)) {
Andres Moree269fc22013-02-12 20:36:29 -05001980 bNeedEncryption = false;
Andres Moreceb8c5d2013-03-18 20:33:49 -05001981 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.h_proto));
Forest Bond92b96792009-06-13 07:38:31 -04001982 if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
1983 if (pTransmitKey == NULL) {
1984 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n");
1985 }
1986 else {
Andres More4e9b5e22013-02-12 20:36:30 -05001987 if (bTKIP_UseGTK == true) {
Forest Bond92b96792009-06-13 07:38:31 -04001988 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n");
1989 }
1990 else {
Malcolm Priestleyb4dc03a2012-11-11 15:45:52 +00001991 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n",
1992 pTransmitKey->dwKeyIndex);
Andres More4e9b5e22013-02-12 20:36:30 -05001993 bNeedEncryption = true;
Forest Bond92b96792009-06-13 07:38:31 -04001994 }
1995 }
1996 }
Forest Bond92b96792009-06-13 07:38:31 -04001997 }
1998 else {
1999
Forest Bond92b96792009-06-13 07:38:31 -04002000 if (pTransmitKey == NULL) {
2001 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n");
2002 dev_kfree_skb_irq(skb);
2003 pStats->tx_dropped++;
2004 return STATUS_FAILURE;
2005 }
Forest Bond92b96792009-06-13 07:38:31 -04002006 }
2007 }
2008
Malcolm Priestleyb674ee12014-05-15 22:49:10 +01002009 pContext = s_vGetFreeContext(pDevice);
2010 if (!pContext) {
2011 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG" pContext == NULL\n");
2012 dev_kfree_skb_irq(skb);
2013 return STATUS_RESOURCES;
2014 }
2015
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002016 pTX_Buffer = (struct vnt_tx_buffer *)&pContext->data[0];
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +01002017
Malcolm Priestleyc2c32da2014-05-31 13:34:57 +01002018 fConvertedPacket = s_bPacketToWirelessUsb(pContext, byPktType,
Malcolm Priestleyd0a2b8f2013-08-15 19:37:04 +01002019 pTX_Buffer, bNeedEncryption,
Malcolm Priestley05cc6172014-04-30 21:31:12 +01002020 skb->len, &pDevice->sTxEthHeader,
Andres Moreb902fbf2013-02-25 20:32:51 -05002021 (u8 *)skb->data, pTransmitKey, uNodeIndex,
Forest Bond92b96792009-06-13 07:38:31 -04002022 pDevice->wCurrentRate,
2023 &uHeaderLen, &BytesToWrite
2024 );
2025
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002026 if (fConvertedPacket == false) {
2027 pContext->in_use = false;
2028 dev_kfree_skb_irq(skb);
2029 return STATUS_FAILURE;
2030 }
Forest Bond92b96792009-06-13 07:38:31 -04002031
Andres More4e9b5e22013-02-12 20:36:30 -05002032 if ( pDevice->bEnablePSMode == true ) {
Forest Bond92b96792009-06-13 07:38:31 -04002033 if ( !pDevice->bPSModeTxBurst ) {
Andres More0cbd8d92010-05-06 20:34:29 -03002034 bScheduleCommand((void *) pDevice,
2035 WLAN_CMD_MAC_DISPOWERSAVING,
2036 NULL);
Andres More4e9b5e22013-02-12 20:36:30 -05002037 pDevice->bPSModeTxBurst = true;
Forest Bond92b96792009-06-13 07:38:31 -04002038 }
2039 }
2040
Andres Moreb902fbf2013-02-25 20:32:51 -05002041 pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
Malcolm Priestleyca347592014-03-22 09:01:28 +00002042 pTX_Buffer->tx_byte_count = cpu_to_le16((u16)BytesToWrite);
Forest Bond92b96792009-06-13 07:38:31 -04002043
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002044 pContext->skb = skb;
2045 pContext->type = CONTEXT_DATA_PACKET;
2046 pContext->buf_len = (u16)BytesToWrite + 4 ; /* USB header */
Forest Bond92b96792009-06-13 07:38:31 -04002047
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01002048 s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
Malcolm Priestley81aec602014-02-27 23:06:11 +00002049 &pDevice->sTxEthHeader.h_dest[0],
Malcolm Priestleyd66caad2013-09-17 19:54:35 +01002050 (u16)(BytesToWrite-uHeaderLen),
2051 pTX_Buffer->fifo_head.wFIFOCtl);
Forest Bond92b96792009-06-13 07:38:31 -04002052
2053 status = PIPEnsSendBulkOut(pDevice,pContext);
2054
Andres More4e9b5e22013-02-12 20:36:30 -05002055 if (bNeedDeAuth == true) {
Andres More3eaca0d2013-02-25 20:32:52 -05002056 u16 wReason = WLAN_MGMT_REASON_MIC_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -04002057
Andres Moreb902fbf2013-02-25 20:32:51 -05002058 bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (u8 *) &wReason);
Forest Bond92b96792009-06-13 07:38:31 -04002059 }
2060
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002061 if (status != STATUS_PENDING) {
2062 pContext->in_use = false;
2063 dev_kfree_skb_irq(skb);
2064 return STATUS_FAILURE;
2065 }
Forest Bond92b96792009-06-13 07:38:31 -04002066
Malcolm Priestley30a05b32014-05-15 22:49:11 +01002067
2068 return 0;
Forest Bond92b96792009-06-13 07:38:31 -04002069}